Как исправить TypeError: Unicode-объекты должны быть закодированы перед хэшированием с помощью ReportLab - PullRequest
1 голос
/ 27 февраля 2020

В последнее время я работаю ReportLab. В настоящее время я хотел бы создать кликабельное оглавление в формате PDF, используя ReportLab.

Когда я пытался увидеть, как это работает, я получаю эту ошибку: TypeError: Unicode-objects must be encoded before hashing

Когда я пытался выполнить этот код на Python 3.7.4 с использованием библиотеки ReportLab:

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)

Я пытался исправить эту проблему, но я не могу исправить это должным образом. Я ценю вашу помощь в этом, пожалуйста.

1 Ответ

2 голосов
/ 27 февраля 2020

Предполагается, что вы должны передавать байты, а не строки, поэтому проблема здесь:

bn=sha1(text+sty.name).hexdigest()

, что вы можете сделать, это изменить следующим образом:

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

Кроме того, вы должен действительно переместить ваш sha1 импорт в начало файла, не нужно вызывать его каждый раз, когда вы запускаете функцию

...