将 JSON 直接转储到 tarfile 中
Dumping JSON directly into a tarfile
我有一个很大的字典对象列表。我想将此列表存储在 tar 文件中以进行远程交换。通过将 json.dumps() 字符串写入以 'w:gz' 模式打开的 tar 文件对象,我已经成功地做到了这一点。
我正在尝试管道实现,以 'w|gz' 模式打开 tar 文件对象。到目前为止,这是我的代码:
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' 是一个生成器,一次 returns 来自数据集的一个字典对象(因此 packet 是一个字典)。
这是我的错误:
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'
在评论的帮助下进行一些故障排除后,错误是在 '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 对象关闭。
谁能帮我弄清楚这是怎么回事?
为什么您认为可以将 tarfile 写入 StringIO?这并不像你想象的那样有效。
这种方法不会出错,但实际上并不是从内存中的对象在内存中创建 tarfile 的方式。
from json import dumps
from io import BytesIO
import tarfile
data = [{'foo': 'bar'},
{'cheese': None},
]
filename = 'fnord'
with BytesIO() as out_stream, tarfile.open(filename, 'w|gz', out_stream) as tar_file:
for packet in data:
out_stream.write(dumps(packet).encode())
我有一个很大的字典对象列表。我想将此列表存储在 tar 文件中以进行远程交换。通过将 json.dumps() 字符串写入以 'w:gz' 模式打开的 tar 文件对象,我已经成功地做到了这一点。
我正在尝试管道实现,以 'w|gz' 模式打开 tar 文件对象。到目前为止,这是我的代码:
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' 是一个生成器,一次 returns 来自数据集的一个字典对象(因此 packet 是一个字典)。
这是我的错误:
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'
在评论的帮助下进行一些故障排除后,错误是在 '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 对象关闭。
谁能帮我弄清楚这是怎么回事?
为什么您认为可以将 tarfile 写入 StringIO?这并不像你想象的那样有效。
这种方法不会出错,但实际上并不是从内存中的对象在内存中创建 tarfile 的方式。
from json import dumps
from io import BytesIO
import tarfile
data = [{'foo': 'bar'},
{'cheese': None},
]
filename = 'fnord'
with BytesIO() as out_stream, tarfile.open(filename, 'w|gz', out_stream) as tar_file:
for packet in data:
out_stream.write(dumps(packet).encode())