gpt4 book ai didi

python - 通过 subprocess.communicate 在 python 脚本之间传输 pickled 对象输出

转载 作者:太空狗 更新时间:2023-10-30 02:45:01 26 4
gpt4 key购买 nike

我有两个 python 脚本:object_generator.py,它们会 pickle 给定的对象并打印它。另一个脚本 object_consumer.py 通过 subprocess.communicate 选择第一个脚本的输出,并尝试使用 pickle.loads 对其进行 unpickle。我无法使这个简单的场景正常工作。这是我的代码:

对象生成器.py

import pickle
import base64

o = {'first':1,'second':2,'third':3,'ls':[1,2,3]}
d = pickle.dumps(o)
print(d)

#Various Approaches I had tried, none of which worked. Ignore this part.
#s = base64.b64decode(d)
#encoded_str = str(d).encode('ascii')
#print('encoded str is :')
#print(encoded_str)
#decoded_str = encoded_str.decode('ascii')
#print('decoded str is :')
#print(decoded_str)
#unpickled_obj = pickle.loads(bytes(decoded_str))
#print(unpickled_obj)
#print(type(d))
#print(codecs.decode(d))

对象消费者.py

import pickle
import subprocess
import os

dr = '"' + os.path.dirname(os.path.abspath(__file__)) + '\\object_generator.py"'

cmd = 'python -u ' + dr

proc = subprocess.Popen(cmd,stdout=subprocess.PIPE)

try:
outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()

# 'out' at this point is something like this :
# b"b'\\x80\\x03}q\......x05K\\x03u.'\r\n"
# DO SOMETHING WITH outs to get back the bytes which can then be
# unpickled using pickle.loads

obj = pickle.loads(outs)
print(obj)

显然,我需要去掉尾随的\r\n 这很容易,但接下来应该做什么?

最佳答案

这里有几个问题。首先,您在 object_generator.py 中打印一个 bytes 对象。在 Python 3.x 中,这将导致 str(obj) 被调用,这意味着 b'yourbyteshere' 被打印。您不需要前导 b' 或尾随 '。要解决此问题,您需要将 bytes 对象编码为字符串。 pickle 使用 'latin-1' 编码,因此我们可以使用它来将 bytes 对象解码为 str。另一个问题是 Windows 默认为 sys.stdout 使用的编码实际上不支持打印解码的 pickle 字符串。因此,我们需要将 sys.stdout* 的默认编码更改为 'latin-1',这样字符串才能以正确的编码到达父进程。

import pickle
import base64
import codecs

o = {'first':1,'second':2,'third':3,'ls':[1,2,3]}
d = pickle.dumps(o)
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='latin-1')
print(d.decode('latin-1'), end='', flush=True) # end='' will remove that extra \r\n

进行这些更改,它应该可以正常工作。

编辑:

另一种选择是将父进程的 PYTHONIOENCODING 环境变量设置为 'latin-1':

env = os.environ.copy()
env['PYTHONIOENCODING'] = 'latin-1'
proc = subprocess.Popen(['python3', 'async2.py'] ,stdout=subprocess.PIPE, env=env)

* 参见 this question有关在 Python 3 中更改 sys.stdout 编码的更多信息。我在这里展示的两种方法都在那里提到。

关于python - 通过 subprocess.communicate 在 python 脚本之间传输 pickled 对象输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26218944/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com