Python 如何更正TypeError:在使用ReportLab进行哈希运算之前,必须对Unicode对象进行编码

Python 如何更正TypeError:在使用ReportLab进行哈希运算之前,必须对Unicode对象进行编码,python,django,datatables,reportlab,python-unicode,Python,Django,Datatables,Reportlab,Python Unicode,最近,我一直在工作ReportLab。目前,我想使用ReportLab生成PDF格式的可点击目录 当我试图了解它是如何工作的时,我一直遇到这样的错误:TypeError:Unicode对象必须在散列之前进行编码 当我尝试使用ReportLablibrary在Python 3.7.4上执行此代码时: class MyDocTemplate(BaseDocTemplate): def __init__(self, filename, **kw): self.allowSpli

最近,我一直在工作
ReportLab
。目前,我想使用
ReportLab
生成PDF格式的可点击目录

当我试图了解它是如何工作的时,我一直遇到这样的错误:
TypeError:Unicode对象必须在散列之前进行编码

当我尝试使用
ReportLab
library在Python 3.7.4上执行此代码时:

class MyDocTemplate(BaseDocTemplate):
    def __init__(self, filename, **kw):
        self.allowSplitting = 0
        apply(BaseDocTemplate.__init__, (self, filename), kw)
        template = PageTemplate('normal', [Frame(2.5*cm, 2.5*cm, 15*cm, 25*cm, id='F1')])
        self.addPageTemplates(template)


    def afterFlowable(self, flowable):
        "Registers TOC entries."
        if flowable.__class__.__name__ == 'Paragraph':
            text = flowable.getPlainText()
            style = flowable.style.name
            if style == 'Heading1':
                level = 0
            elif style == 'Heading2':
                level = 1
            else:
                return
            E = [level, text, self.page]
            #if we have a bookmark name append that to our notify data
            bn = getattr(flowable,'_bookmarkName',None)
            if bn is not None: E.append(bn)
            self.notify('TOCEntry', tuple(E))

centered = PS(name = 'centered',
    fontSize = 30,
    leading = 16,
    alignment = 1,
    spaceAfter = 20)

h1 = PS(
    name = 'Heading1',
    fontSize = 14,
    leading = 16)


h2 = PS(name = 'Heading2',
    fontSize = 12,
    leading = 14)


# Build story.
story = []

toc = TableOfContents()
toc.levelStyles = [
    PS(fontName='Times-Bold', fontSize=20, name='TOCHeading1', leftIndent=20, firstLineIndent=-20, spaceBefore=10, leading=16),
    PS(fontSize=18, name='TOCHeading2', leftIndent=40, firstLineIndent=-20, spaceBefore=5, leading=12),
]
story.append(toc)

def doHeading(text,sty):
    from hashlib import sha1
    #create bookmarkname
    bn=sha1(text+sty.name).hexdigest()
    #modify paragraph text to include an anchor point with name bn
    h=Paragraph(text+'<a name="%s"/>' % bn,sty)
    #store the bookmark name on the flowable so afterFlowable can see this
    h._bookmarkName=bn
    story.append(h)

story.append(Paragraph('<b>Table of contents</b>', centered))
story.append(PageBreak())
doHeading('First heading', h1)
story.append(Paragraph('Text in first heading', PS('body')))
doHeading('First sub heading', h2)
story.append(Paragraph('Text in first sub heading', PS('body')))
story.append(PageBreak())
doHeading('Second sub heading', h2)
story.append(Paragraph('Text in second sub heading', PS('body')))
story.append(PageBreak())
doHeading('Last heading', h1)
story.append(Paragraph('Text in last heading', PS('body')))
doc = MyDocTemplate('mintoc.pdf')
doc.multiBuild(story)
类MyDocTemplate(BaseDocTemplate):
def u uu init uuuu(self,文件名,**kw):
self.allowSplitting=0
应用(BaseDoctTemplate.\uuuuu init\uuuuuuuu,(self,文件名),kw)
template=PageTemplate('normal',[Frame(2.5*cm,2.5*cm,15*cm,25*cm,id='F1'))
self.addPageTemplates(模板)
def可后流式(自动、可流动):
“注册TOC条目。”
如果是可流动的。类别名称=段落:
text=flowable.getPlainText()
style=flowable.style.name
如果样式=='Heading1':
级别=0
elif style=='Heading2':
级别=1
其他:
返回
E=[级别,文本,self.page]
#如果我们有书签名称,请将其附加到notify数据中
bn=getattr(可流动,“书签名称”,无)
如果bn不是None:E.append(bn)
self.notify('TOCEntry',元组(E))
居中=PS(名称=‘居中’,
fontSize=30,
领先=16,
对齐=1,
spaceAfter=20)
h1=PS(
名称='Heading1',
fontSize=14,
领先=16)
h2=PS(名称='Heading2',
fontSize=12,
领先=14)
#构建故事。
故事=[]
toc=目录()
toc.levelStyles=[
PS(fontName='Times-Bold',fontSize=20,name='toheading1',leftIndent=20,firstLineIndent=-20,spaceBefore=10,leading=16),
PS(fontSize=18,name='TOCHeading2',leftIndent=40,firstLineIndent=-20,spaceBefore=5,leading=12),
]
故事附加(toc)
标题(文本,sty):
从hashlib导入sha1
#创建书签名
bn=sha1(text+sty.name).hexdigest()
#修改段落文本以包含名为bn的定位点
h=段落(文本+''%bn,sty)
#将书签名称存储在FlowTable上,以便AfterFlowTable可以看到这一点
h、 _bookmarkName=bn
故事。附加(h)
附加(段落(“目录”,居中))
story.append(PageBreak())
doHeading(“第一个航向”,h1)
附加(段落('第一标题中的文本',PS('正文'))
doHeading(“第一副标题”,h2)
故事。附加(段落(“第一小标题中的文本”,PS(“正文”))
story.append(PageBreak())
双品目(“第二副品目”,h2)
附加(段落(‘第二小标题中的文本’、PS(‘正文’))
story.append(PageBreak())
doHeading('最后一个标题',h1)
附加(段落(“最后一个标题中的文本”,PS(“正文”))
doc=MyDocTemplate('mintoc.pdf')
多版本文档(故事)

我试图解决此问题,但无法正确解决此问题。非常感谢您在这方面的帮助。

您应该传递字节,而不是字符串,因此问题在于:

bn=sha1(text+sty.name).hexdigest()
你能做的就是这样改变它:

bn=sha1((text+sty.name).encode("utf8")).hexdigest()

此外,您应该将
sha1
import移到文件的顶部,无需每次运行函数时调用它

它会给出相同的错误“TypeError:Unicode对象必须在散列之前进行编码”它会在何处给出此错误?请将堆栈跟踪添加到问题72 def doHeading(text,sty):73#创建书签名-->74 bn=sha1(text+sty.name)。编码(“utf8”).hexdigest()75#修改段落文本,以包含一个名为bn 76 h=段落(text+'%bn,sty)的锚定点TypeError:在散列
bn=sha1(text+sty.name)之前必须对Unicode对象进行编码。编码(“utf8”)。hexdigest()
错误!仔细看看我的建议,你把
()
放错地方了。它应该是
bn=sha1((text+sty.name).encode(“utf8”)).hexdigest()