UnicodeEncodeError:“ latin-1”编解码器无法编码字符“ \ u2013”​​(写入PDF)

时间:2019-06-25 20:18:52

标签: python pdf unicode fpdf python-3.7

使用python写入.pdf时,Unicode的内容可变,我遇到了问题。

正在输出此错误:

UnicodeEncodeError: 'latin-1' codec can't encode character '\u2013'

这基本上是什么?

我尝试使用该变量,其中的内容带有'em破折号',并使用例如'.encode('utf-8')'重新定义,例如,如下:

Body = msg.Body

BodyC = Body.encode('utf-8')

现在我得到以下错误:

Traceback (most recent call last):
  File "script.py", line 37, in <module>
    pdf.cell(200, 10, txt="Bod: " + BodyC,  ln=4, align="C")
TypeError: can only concatenate str (not "bytes") to str

下面是我的完整代码,如何才能简单地在“ Body”变量内容中修复Unicode错误。

转换为utf-8之外的任何内容,都转换为westernlatin-1。有什么建议吗?

完整代码:

from fpdf import FPDF
import win32com.client

outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
msg = outlook.OpenSharedItem(r"C:\User\language\python\Msg-To-PDF\test_msg.msg")

print (msg.SenderName)
print (msg.SenderEmailAddress)
print (msg.SentOn)
print (msg.To)
print (msg.CC)
print (msg.BCC)
print (msg.Subject)
print (msg.Body)

SenderName = msg.SenderName
SenderEmailAddress = msg.SenderEmailAddress
SentOn = msg.SentOn
To = msg.To
CC = msg.CC
BCC = msg.BCC
Subject = msg.Subject
Body = msg.Body
BodyC = Body.encode('utf-8')

pdf = FPDF()
pdf.add_page()

# pdf.add_font('DejaVu', '', 'DejaVuSansCondensed.ttf', uni=True)
pdf.set_font("Helvetica", style = '', size = 11)
pdf.cell(200, 10, txt="From: " + SenderName, ln=1, align="C")
# pdf.cell(200, 10, border=SentOn, ln=1, align="C")
pdf.cell(200, 10, txt="To: " + To, ln=1, align="C")
pdf.cell(200, 10, txt="CC: " + CC, ln=1, align="C")
pdf.cell(200, 10, txt="BCC: " + BCC, ln=1, align="C")
pdf.cell(200, 10, txt="Subject: " + Subject, ln=1, align="C")
pdf.cell(200, 10, txt="Bod: " + BodyC,  ln=4, align="C")

pdf.output("Sample.pdf")
  • 如何在'latin1'中进行更改?

  • 是否仅在全球范围内解决这些问题?

3 个答案:

答案 0 :(得分:1)

一种解决方法是将所有文本转换为latin-1编码,然后再传递给库。您可以使用以下命令进行操作:

text2 = text.encode('latin-1', 'replace').decode('latin-1')

text2将不包含任何非拉丁1字符。但是,某些字符可能会替换为?

答案 1 :(得分:1)

您还可以通过.set_doc_option()方法(文档here)更改编码。我尝试了对我有用的Erik方法,但是在添加了更多复杂性(例如第二个PDF并使用了需要创建新类的write_html()方法)之后,我又回到了同样的错误。如您所说,更改整个文档的编码应该可以解决整个问题。

readthedocs页面上说,您只能使用latin-1或Windows-1252,但是根据调试器,pdf.set_doc_option('core_fonts_encoding', 'utf-8')对我有用。请注意,某些字符将需要修复,例如在PDF中显示为¢™的撇号(')。

希望这是您正在寻找的全球解决方案,即使延迟了几个月!

答案 2 :(得分:0)

此错误的原因是您试图在PDF中呈现latin-1编码的代码范围之外的字符。 FPDF使用latin-1作为其所有内置字体的默认编码。

因此,作为解决方法,您可以从文本中删除所有不适合latin-1编码的字符。 (有关此解决方法,请参见我的其他答案)。

要修复此错误并能够在PDF中呈现这些字符,您需要使用支持更多字符的字体。为了解决这个问题,FPDF库支持Unicode字体。

例如,您可以获得免费的Google Noto fonts,它支持多种Unicode端点。对于大多数西方语言,我建议使用NotoSans字体集。但是您还可以获取许多其他语言和脚本的字体,包括中文,希伯来语或阿拉伯语。

以下是在代码中为FPDF启用Unicode字体的方法:

首先,您需要告诉FPDF库可以在哪里找到字体文件。在此示例中,我将其设置为当前文件夹的子文件夹fonts

import fpdf
fpdf.set_global("SYSTEM_TTFONTS", os.path.join(os.path.dirname(__file__),'fonts'))

然后,您需要将字体添加到PDF文档中。在此示例中,我为常规,粗体,斜体和粗斜体样式添加了NotoSans字体:

pdf = fpdf.FPDF()
pdf.add_font("NotoSans", style="", fname="NotoSans-Regular.ttf", uni=True)
pdf.add_font("NotoSans", style="B", fname="NotoSans-Bold.ttf", uni=True)
pdf.add_font("NotoSans", style="I", fname="NotoSans-Italic.ttf", uni=True)
pdf.add_font("NotoSans", style="BI", fname="NotoSans-BoldItalic.ttf", uni=True)

现在,您可以通过set_font()在PDF文档中正常使用新字体了。这是普通文本的示例:

pdf.set_font("NotoSans", size=12)