【发布时间】:2016-08-23 19:22:37
【问题描述】:
我有一个很大的 dict 对象列表。我想将此列表存储在 tar 文件中以进行远程交换。我通过将 json.dumps() 字符串写入以“w:gz”模式打开的 tarfile 对象成功地做到了这一点。
我正在尝试管道实现,以“w|gz”模式打开 tarfile 对象。到目前为止,这是我的代码:
from json import dump
from io import StringIO
import tarfile
with StringIO() as out_stream, tarfile.open(filename, 'w|gz', out_stream) as tar_file:
for packet in json_io_format(data):
dump(packet, out_stream)
此代码在函数“write_data”中。 'json_io_format' 是一个生成器,它一次从数据集中返回一个 dict 对象(因此数据包是一个 dict)。
这是我的错误:
Traceback (most recent call last):
File "pdml_parser.py", line 35, in write_data
dump(packet, out_stream)
File "/.../anaconda3/lib/python3.5/tarfile.py", line 2397, in __exit__
self.close()
File "/.../anaconda3/lib/python3.5/tarfile.py", line 1733, in close
self.fileobj.close()
File "/.../anaconda3/lib/python3.5/tarfile.py", line 459, in close
self.fileobj.write(self.buf)
TypeError: string argument expected, got 'bytes'
在 cmets 的帮助下进行了一些故障排除后,当 'with' 语句退出并尝试调用上下文管理器 __exit__ 时会导致错误。我相信这又会调用 TarFile.close()。如果我从“with”语句中删除 tarfile.open() 调用,并故意省略 TarFile.close(),我会得到以下代码:
with StringIO() as out_stream:
tarfile.open(filename, 'w|gz', out_stream) as tar_file:
for packet in json_io_format(data):
dump(packet, out_stream)
此版本的程序完成,但不生成输出文件 'filname' 并产生此错误:
Exception ignored in: <bound method _Stream.__del__ of <targile._Stream object at 0x7fca7a352b00>>
Traceback (most recent call last):
File "/.../anaconda3/lib/python3.5/tarfile.py", line 411, in __del__
self.close()
File "/.../anaconda3/lib/python3.5/tarfile.py", line 459, in close
self.fileobj.write(self.buf)
TypeError: string argument expected, got 'bytes'
我相信这是由垃圾收集器引起的。有东西阻止 TarFile 对象关闭。
谁能帮我弄清楚这里发生了什么?
【问题讨论】:
-
您的异常不是在循环期间发生,而是在
with块的末尾(循环结束后)。对tarfile上下文管理器的__close__调用以某种我不完全理解的方式存在数据问题(因此这是评论而不是答案)。为了简化调试,您或许可以通过dumping 一个不带循环的值进行测试。 -
我重新编写了函数以从 with 语句中删除 tarfile 声明并得到相同的错误。我删除了 tar_file.close() ,现在当垃圾收集器尝试删除流对象时出现错误。所以是的,tarfile 关闭有问题。我将修改我的问题以反映这一点,感谢您的提示。
标签: python json python-3.x tarfile