我有一个使用 ReportLab 创建报告的 python 脚本,该脚本已经过测试并且按预期工作,但是有时我会收到以下错误消息
TraceBack info:
File "C:\tools\LegionellaTool.py", line 605, in <module>
createReport(selectedCoolingTowers, Report_outputs_folder, dbo_COLGIS, openPDF)
Error Info:
..\Objects\moduleobject.c:50: bad argument to internal function
605路是
createReport(selectedCoolingTowers, Report_outputs_folder, dbo_COLGIS, openPDF)
createReport 是...创建报告的函数。 我已经调试了代码,没有遇到任何错误,什么可能会导致错误出现,该错误仅偶尔发生,而在其他情况下,报告创建得很好。
编辑=====创建报告代码
def createReport(myReportTable, myReportFolder, M3Table, OpenPDF):
global Author
global TimeStamp
## myReportTable = gp.GetParameterAsText(0)
## myReportFolder = gp.GetParameterAsText(1)
## M3Table = gp.GetParameterAsText(2)
## OpenPDF = gp.GetParameterAsText(3)
Author = getpass.getuser() #gets OS user name
TimeStamp = str(datetime.datetime.now().hour) + ':' + str(datetime.datetime.now().minute) + ' on the ' + str(datetime.date.today().day) + '/' + str(datetime.date.today().month) + '/' + str(datetime.date.today().year)
#add time stamp to file name
myFile = myReportFolder + os.sep + 'CoolingTowersForInspection_' + str(datetime.datetime.now().hour) + '_' + str(datetime.datetime.now().minute) + '_' + str(datetime.date.today().day) + '_' + str(datetime.date.today().month) + '_' + str(datetime.date.today().year) + '.pdf'
c = reportlab.pdfgen.canvas.Canvas(myFile)
#creates sectors array
sectors = []
sectors.append('NW')
sectors.append('NE')
sectors.append('SW')
sectors.append('SE')
for sector in sectors:
#sector header
#framePage(c, 'Cooling Towers for Inspection - ' + sector + ' sector')
title = 'Cooling Towers for Inspection - ' + sector + ' sector'
c.setFont('Helvetica',20) #title font
c.drawString(reportlab.lib.units.inch, 10.5 * reportlab.lib.units.inch, title) #creates title
c.setFont('Helvetica',10) #header and footer font
#creates header
c.drawCentredString(4.135 * reportlab.lib.units.inch, 0.75 * reportlab.lib.units.inch,
'Report generated by ' + Author + ' at ' + TimeStamp + ' - Page %d' % c.getPageNumber())
#creates footer
c.drawCentredString(4.135 * reportlab.lib.units.inch, 11.00 * reportlab.lib.units.inch,
'Environmental Services')
#draw a border
c.setStrokeColorRGB(1,0,0)
c.setLineWidth(5)
c.line(0.8 * reportlab.lib.units.inch, reportlab.lib.units.inch, 0.8 * reportlab.lib.units.inch, 10.75 * reportlab.lib.units.inch)
#reset carefully afterwards
c.setLineWidth(1)
c.setStrokeColorRGB(0,0,0)
c.setFont('Helvetica', 10)
#gets towers in that sector
myTowers = arcpy.SearchCursor(myReportTable,"\"SECTOR\" = '" + sector + "'","","")
selTower = myTowers.next()
y = 730
if selTower is not None:
while selTower:
#insert page break when close to the end of the page
if y < 110:
c.showPage()
y = 730
framePage(c, 'Cooling Towers for Inspection - ' + sector + ' sector')
if selTower.TOWER_NAME <> None:
c.drawString(100, y, string.strip(selTower.TOWER_NAME))
else:
c.drawString(100, y, "na")
y = y - 12
if selTower.TOWER_ADDRESS <> None:
c.drawString(100, y, string.strip(selTower.TOWER_ADDRESS))
else:
c.drawString(100, y, "na")
y = y - 12
c.drawString(100, y, "Number of towers: " + str(int(selTower.NUMBER_OF_TOWERS)) + " ; M3 Code: " + selTower.UKEY + " ; Distance band: " + str(int(selTower.distance)) + " meters")
y = y - 12
inspectString = ""
if selTower.TOWER_RATING <> None:
inspectString = "Inspection rating: " + selTower.TOWER_RATING
else:
inspectString = "Inspection rating: na;"
if selTower.TOWER_LAST_INSPECTION <> None:
t = selTower.TOWER_LAST_INSPECTION
strLastInspection = t.strftime("%A, %d %b %Y")
inspectString = inspectString + " Last inspection: " + strLastInspection
#inspectString = inspectString + " Last inspection: " + selTower.TOWER_LAST_INSPECTION
else:
inspectString = inspectString + " Last inspection: na"
c.drawString(100, y, inspectString)
y = y - 12
c.drawString(100, y, "Contacts:")
y = y - 12
myTowerUKEY = selTower.UKEY
#gets contacts for that cooling tower
myTowerContacts = arcpy.SearchCursor(M3Table,"\"UKEY\" = '" + myTowerUKEY + "'","","")
selContact = myTowerContacts.next()
while selContact:
if y < 110:
c.showPage()
y = 730
framePage(c, 'Cooling Towers for Inspection - ' + sector + ' sector')
contact = ""
if selContact.TITLE <> None:
if string.strip(selContact.TITLE) <> "":
contact = string.strip(selContact.TITLE) + " "
if selContact.FIRSTNAME <> None:
contact = contact + selContact.FIRSTNAME + " "
if selContact.FAMILYNAME <> None:
contact = contact + selContact.FAMILYNAME + " "
if selContact.JOBTITLE <> None:
contact = contact + "(" + selContact.JOBTITLE + ") "
if selContact.TELW <> None:
contact = contact + selContact.TELW + "(work) "
if selContact.MOBILE <> None:
if string.strip(selContact.MOBILE) <> "":
contact = contact + string.strip(selContact.MOBILE) + "(mobile) "
if selContact.TELH <> None:
if string.strip(selContact.TELH) <> "":
contact = contact + string.strip(selContact.TELH) + "(home)"
contact = string.strip(contact)
c.drawString(100, y, contact)
y = y - 12
selContact = myTowerContacts.next()
y = y - 12
del myTowerContacts
selTower = myTowers.next()
else:
c.drawString(100, y, "no cooling towers for inspection in this sector")
c.showPage() #insert page break after each sector
del myTowers
c.save()
if OpenPDF == "true":
os.startfile(myFile)
#function that creates each page
def framePage(canvas, title):
canvas.setFont('Helvetica',20) #title font
canvas.drawString(reportlab.lib.units.inch, 10.5 * reportlab.lib.units.inch, title) #creates title
canvas.setFont('Helvetica',10) #header and footer font
#creates header
canvas.drawCentredString(4.135 * reportlab.lib.units.inch, 0.75 * reportlab.lib.units.inch,
'Report generated by ' + Author + ' at ' + TimeStamp + ' - Page %d' % canvas.getPageNumber())
#creates footer
canvas.drawCentredString(4.135 * reportlab.lib.units.inch, 11.00 * reportlab.lib.units.inch,
'Environmental Services')
#draw a border
canvas.setStrokeColorRGB(1,0,0)
canvas.setLineWidth(5)
canvas.line(0.8 * reportlab.lib.units.inch, reportlab.lib.units.inch, 0.8 * reportlab.lib.units.inch, 10.75 * reportlab.lib.units.inch)
#reset carefully afterwards
canvas.setLineWidth(1)
canvas.setStrokeColorRGB(0,0,0)
编辑编号 2 *
完整的追溯在这里
Traceback (most recent call last):
File "C:\tools\LegionellaTool.py", line 613, in <module>
createReport(selectedCoolingTowers, Report_outputs_folder, dbo_COLGIS, openPDF)
File "C:\tools\LegionellaTool.py", line 120, in createReport
c.drawString(reportlab.lib.units.inch, 10.5 * reportlab.lib.units.inch, title) #creates title
File "c:\python26\arcgis10.0\lib\site-packages\reportlab\pdfgen\canvas.py", line 1481, in drawString
t.textLine(text)
File "c:\python26\arcgis10.0\lib\site-packages\reportlab\pdfgen\textobject.py", line 426, in textLine
self._code.append('%s T*' % self._formatText(text))
File "c:\python26\arcgis10.0\lib\site-packages\reportlab\pdfgen\textobject.py", line 393, in _formatText
for f, t in pdfmetrics.unicode2T1(text,[font]+font.substitutionFonts):
SystemError: ..\Objects\moduleobject.c:50: bad argument to internal function
<type 'exceptions.SystemExit'>: 1
谢谢
根据我的经验,ReportLab 的间歇性错误通常是由尝试渲染可能包含“奇怪”内容的文本时出现的问题引起的,例如字符集的意外字符或空值。查看您的代码,我没有注意到任何明显会导致问题的内容,但您可能想研究某些内容包含意外值的可能性。
特别是,我会查看处理
selContact
的代码,看看它的任何属性是否意外为空或只是不是可能导致错误的字符串。
没有完整的堆栈跟踪,很难说出更具体的内容。
预计到达时间
根据现在提供的堆栈跟踪,看起来问题要么出在您尝试绘制的
title
变量中,要么出在用于绘制字符串的字体上。不过,查看您的代码,我没有注意到任何问题,也没有任何迹象表明引发错误的代码部分存在间歇性问题。
在过去的几周里,这条消息让我发疯,我终于弄清楚了导致此错误的两件事以及如何修复它们:
正如 G Gordon Worley III 建议的那样,如果您尝试使用不正确的元素构建报告,它可能会出现。
修复:查找哪个元素已损坏或在 ArcGIS 之外调试您的程序,您将获得更明确的错误消息。
如果你的Python安装有点混乱,它可能会出现。对我来说,我将 ReportLab 文件包含在与脚本相同的文件夹中,以使其更易于分发。但我之前也在我的 Python 安装文件夹中安装了 ReportLab。不知何故,这让 ArcGIS 感到困惑。
修复:删除Python??/(ArcGIS??.?/)Lib/site-packages/reportlab文件夹,以便您的脚本只有一个库选项。
我希望这会对某人有所帮助。