python - open(..., encoding="") vs str.encode(encoding="")
问题描述
问题:和 和
有什么不一样?它们似乎(有时)产生不同的输出。open(<name>, "w", encoding=<encoding>)
open(<name>, "wb") + str.encode(<encoding>)
上下文:
在使用PyFPDF(版本 1.7.2)时,我对类进行了子FPDF
类化,除其他外,添加了我自己的输出方法(获取pathlib.Path
对象)。在查看原始FPDF.output()
方法的来源时,我注意到几乎所有这些都是参数解析 - 唯一相关的位是
#Finish document if necessary
if(self.state < 3):
self.close()
[...]
f=open(name,'wb')
if(not f):
self.error('Unable to create output file: '+name)
if PY3K:
# manage binary data as latin1 until PEP461 or similar is implemented
f.write(self.buffer.encode("latin1"))
else:
f.write(self.buffer)
f.close()
看到这一点,我自己的实现看起来像这样:
def write_file(self, file: Path) -> None:
if self.state < 3:
# See FPDF.output()
self.close()
file.write_text(self.buffer, "latin1", "strict")
这似乎有效 - 在指定路径创建了一个 .pdf 文件,然后 chrome 打开了它。但它完全是空白的,即使我添加了图像和文本。经过数小时的试验,我终于找到了一个有效的版本(产生了一个非空的 pdf 文件):
def write_file(self, file: Path) -> None:
if self.state < 3:
# See FPDF.output()
self.close()
# using .write_text(self.buffer, "latin1", "strict") DOES NOT WORK AND I DON'T KNOW WHY
file.write_bytes(self.buffer.encode("latin1", "strict"))
查看pathlib.Path
源代码,它io.open
用于Path.write_text()
. 由于所有这些都是 Python 3.8,io.open
并且构建open()
是相同的.
注意:
FPDF.buffer
是 类型str
,但包含二进制数据(pdf 文件)。可能是因为该库最初是为 Python 2 编写的。
解决方案
两者应该相同(有细微差别)。
我喜欢open
这种方式,因为它是明确且更短的,OTOH 如果你想处理编码错误(例如对用户来说更好的错误),应该使用decode
/ encode
(也许在'\n'.split(s), and keeping line numbers)
注意:如果你使用第一种方法 ( open
),你应该只使用r
or w
,所以不用b
. 对于您的问题的标题,您似乎确实正确,但请检查您的示例是否保留b
,并且可能为此,它使用了encoding
. OTOH 代码看起来很旧,我认为“.encoding”刚刚完成,因为它在 Python2 思维方式中会更自然。
注意:我也将替换strict
为backslashreplace
进行调试。并且可能您可能想要检查并打印(可能只是 ord)self.buffer
这两种方法的前几个字符,以查看之前是否存在实质性差异file.write
。
我会file.flush()
在这两个功能上添加一个。这是差异之一:缓冲不同,我会确保关闭文件。Python 会这样做,但是在调试时,尽可能快地查看文件的内容很重要(以及在异常之后)。垃圾收集器无法保证这一切。也许您正在阅读尚未刷新的文本文件。
推荐阅读
- c# - 试图在我的操作系统中制作一个可点击的主页按钮
- javascript - 无法访问数组中的对象 - Javascript
- angular - Angular,foreach 订阅
- c# - 将任务 C# Try-Catch 异常消息编写到 SQL 表中
- swift - 仅针对 SpriteKit 中的特定对象恢复原状
- c++ - 我的数独程序出现问题,出现一些错误代码
- time-series - ARIMA() error TypeError: __new__() got an unexpected keyword argument 'start'
- javascript - 如何从同一个输入框中获取多个输入并存储它们?
- node.js - 在 Callable Firebase Functions 中获取请求 URL
- android - 如何将 @Parcelize 与 createTypedArray(Creator) 一起使用?