UnicodeEncodeError: 'latin-1' codec can't encode character '\u2013' (writing to PDF)
UnicodeEncodeError: 'latin-1' codec can't encode character '\u2013' (writing to PDF)
我在使用 python 写入 .pdf 时遇到了 Unicode
的问题,其中包含可变内容。
它正在输出这个错误:
UnicodeEncodeError: 'latin-1' codec can't encode character '\u2013'
它基本上是被 em dash 抓住了。
我尝试使用那个变量,其中内容有一个 'em dash' 并用一个 '.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
或 western
,“latin-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'
?
- 是否要在全球范围内解决这些问题?
解决方法是在将所有文本传递到库之前将其转换为 latin-1 编码。您可以使用以下命令执行此操作:
text2 = text.encode('latin-1', 'replace').decode('latin-1')
text2
将没有任何 non-latin-1 个字符。但是,某些字符可能会替换为 ?
此错误的原因是您试图在 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)
您还可以通过 .set_doc_option()
方法(文档 here)更改编码。我尝试了 Erik 的方法,它对我有用,但是在添加了一些更复杂的东西(例如第二个 PDF 并使用需要创建新的 class 的 write_html() 方法)之后,我又回到了有同样的错误。更改整个文档的编码应该可以解决您所说的整体问题。
readthedocs 页面说您只能使用 latin-1 或 windows-1252,但根据调试器,pdf.set_doc_option('core_fonts_encoding', 'utf-8')
对我有效。请注意,有些字符需要修复,例如在 PDF 中显示为 [TM] 的撇号 (')。
希望这是您正在寻找的此问题的全局修复程序,即使晚了几个月!
我正在尝试对 Erik 的解决方案进行一些更改,它非常适合混合使用英语和阿拉伯语文本。下面发布了使用 pyFPDF 生成 PDF 的示例代码。
from datetime import datetime
def getFileName():
now=datetime.now()
time = now.strftime('%d_%H_%M_%S')
filename = "Test_"+time + ".pdf"
return filename
from fpdf import FPDF
pdf = FPDF()
#Download NotoSansArabic-Regular.ttf from Google noto fonts
pdf.add_font("NotoSansArabic", style="", fname="./fonts/NotoSansArabic-Regular.ttf", uni=True)
pdf.add_page()
pdf.set_font('Arial', '', 12)
pdf.write(8, 'Hello World')
pdf.ln(8)
# مرحبا Marhaba in arabic
pdf.set_font('NotoSansArabic', '', 12)
text = 'مرحبا'
pdf.write(8, text)
pdf.ln(8)
pdf.output(getFileName(), 'F')
我在使用 python 写入 .pdf 时遇到了 Unicode
的问题,其中包含可变内容。
它正在输出这个错误:
UnicodeEncodeError: 'latin-1' codec can't encode character '\u2013'
它基本上是被 em dash 抓住了。
我尝试使用那个变量,其中内容有一个 'em dash' 并用一个 '.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
或 western
,“latin-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'
?
- 是否要在全球范围内解决这些问题?
解决方法是在将所有文本传递到库之前将其转换为 latin-1 编码。您可以使用以下命令执行此操作:
text2 = text.encode('latin-1', 'replace').decode('latin-1')
text2
将没有任何 non-latin-1 个字符。但是,某些字符可能会替换为 ?
此错误的原因是您试图在 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)
您还可以通过 .set_doc_option()
方法(文档 here)更改编码。我尝试了 Erik 的方法,它对我有用,但是在添加了一些更复杂的东西(例如第二个 PDF 并使用需要创建新的 class 的 write_html() 方法)之后,我又回到了有同样的错误。更改整个文档的编码应该可以解决您所说的整体问题。
readthedocs 页面说您只能使用 latin-1 或 windows-1252,但根据调试器,pdf.set_doc_option('core_fonts_encoding', 'utf-8')
对我有效。请注意,有些字符需要修复,例如在 PDF 中显示为 [TM] 的撇号 (')。
希望这是您正在寻找的此问题的全局修复程序,即使晚了几个月!
我正在尝试对 Erik 的解决方案进行一些更改,它非常适合混合使用英语和阿拉伯语文本。下面发布了使用 pyFPDF 生成 PDF 的示例代码。
from datetime import datetime
def getFileName():
now=datetime.now()
time = now.strftime('%d_%H_%M_%S')
filename = "Test_"+time + ".pdf"
return filename
from fpdf import FPDF
pdf = FPDF()
#Download NotoSansArabic-Regular.ttf from Google noto fonts
pdf.add_font("NotoSansArabic", style="", fname="./fonts/NotoSansArabic-Regular.ttf", uni=True)
pdf.add_page()
pdf.set_font('Arial', '', 12)
pdf.write(8, 'Hello World')
pdf.ln(8)
# مرحبا Marhaba in arabic
pdf.set_font('NotoSansArabic', '', 12)
text = 'مرحبا'
pdf.write(8, text)
pdf.ln(8)
pdf.output(getFileName(), 'F')