2

我有一个使用 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

谢谢

4

2 回答 2

0

在过去的几周里,这条消息让我发疯了,我终于弄清楚了导致此错误的 2 件事以及如何解决它们:

  • 正如 G Gordon Worley III 建议的那样,如果您尝试使用不正确的元素构建报告,它可能会出现。

    修复:查找损坏的元素或在 ArcGIS 之外调试您的程序,您将收到更明确的错误消息。

  • 如果您的 Python 安装有点混乱,它可能会出现。发生在我身上的是,我将 ReportLab 文件包含在与我的脚本相同的文件夹中,以使其更易于分发。但我之前也在我的 Python 安装文件夹中安装了 ReportLab。不知何故,这让 ArcGIS 感到困惑。

    修复:删除 Python??/(ArcGIS??.?/)Lib/site-packages/reportlab 文件夹,以便您的脚本只有一个库选项。

我希望这会对某人有所帮助。

于 2014-06-10T13:51:38.423 回答
0

根据我的经验,ReportLab 的间歇性错误通常是由尝试呈现可能包含“奇怪”内容的文本时出现的问题引起的,例如字符集的意外字符或空值。查看您的代码,我没有注意到任何明显会导致问题的东西,但您可能想调查某些东西是否包含意外值。

特别是,我会看一下处理的代码selContact,看看它的任何属性是否意外地为空或只是不是可能导致错误的字符串。

如果没有完整的堆栈跟踪,很难说出更具体的内容。

预计到达时间

根据现在提供的堆栈跟踪,看起来问题必须与title您尝试绘制的变量或用于绘制字符串的字体有关。但是,查看您的代码,我没有注意到任何问题,也没有任何迹象表明引发错误的代码部分存在间歇性问题。

于 2013-07-31T13:30:40.713 回答