提问人:caveman 提问时间:12/26/2020 更新时间:7/6/2021 访问量:504
如何将 STDIN 发送到 Popen 进程两次,每次都使用 EOF?
How to send STDIN twice to Popen process, each time with EOF?
问:
我有这部分代码:
for stdin in stdins:
p.stdin.write(stdin)
它将字符串写入进程的 STDIN。stdin
p
挑战在于:该过程希望在进入下一个 STDIN 之前看到 EOF。p
对于上面的循环,问题在于进程将后续视为第一个 STDIN 输入集合的输入。因为,如前所述,希望在移动到后续字段之前看到 EOF。p.stdin.write(stdin)
p
p
所以,我的问题是:如何在Python中解决这个问题?该过程需要看到如下内容:
for stdin in stdins:
p.stdin.write(stdin)
p.stdin.send_eof()
约束:解决方案不得使用 pexpect。
答:
EOF不是一个字符,它只是意味着没有更多的数据可以读取。
因此,我不相信你所追求的东西在 Python 或大多数其他语言中是可能的。
评论
ctrl + D
p.stdin.close()
p.stdin
当我尝试在python中用几个子进程进行异步渲染时,我遇到了同样的问题,这些子进程需要以低延迟与主进程通信。
当我使用 时,我发现子进程在发生或主进程退出之前无法获得任何内容,既发送 EOF 信号,又使 PIPE 成为一次性的。当然,我试过了,等等,但没有一个奏效。subprocess.popen()
stdin=subprocess.PIPE
stdin.close()
stdin.writelines()
stdin.flush()
pickle.dump()
但是有一种方法可以使用 NumPy 与子进程重复通信。
ndarray.tofile 可以直接将数组发送到 File 对象。尽管文档声明它等同于 file.write(a.tobytes()),但它确实有意义。我很困惑,直到我在文档页面的末尾读到这个:
当 fid 是文件对象时,数组内容将直接写入文件,绕过文件对象的 write 方法。因此,tofile 不能与支持压缩的文件对象(例如 GzipFile)或不支持 fileno() 的类文件对象(例如 BytesIO)一起使用。
其实,我认为这是我的错。任何带有调用方法的函数都不可避免地无法发送 EOF,除非我们绕过该方法,如果不使用一些 C 扩展(如 NumPy)是不可能的。file.write()
write()
write()
为了通过PIPE发送常规数据,现在有两种方式:
NumPy 支持 ,这意味着您可以直接将消息打包到对象数组中。参见 numpy.lib.format。
dtype=object
存储对象数组,即包含任意 Python 对象元素的数组。包含对象数组的文件不可映射,但可以读取和写入磁盘。
如果 Struct 具有常规模式,您可以将 Struct 声明为 dtype 来打包您的消息,这就是我的情况。这是我的例子。
task = np.dtype([( "index", np.uint8 ), ( "text", np.unicode_, 128 ), ( "color", np.uint8, 2 ), ( "size", np.uint8 )]) for i in range(123): np.empty(1, dtype=task).tofile(s.stdin) # s is the subprocess' name. time.sleep(1)
然后我成功地在子进程中分别获得了 123 次消息。
我真的希望这能帮助到你。因为我花了将近 4 天的时间才找到这个解决方案。我几乎正在考虑使用磁盘上的真实文件来完成进程之间的通信 - 这应该更慢 - 但多亏了 NumPy,我的调试终于结束了......
另外,我认为发送 EOF 没有意义。您可以在 python 控制台中尝试此操作。np.save()
>>> import numpy as np
>>> import sys
>>> a = np.arange(100).reshape(10,10)
>>> a.tofile(sys.stdout.buffer)
... some garbled characters ...
>>> a.tofiler(sys.stdout)
... some garbled characters ...
>>> np.save(sys.stdout.buffer, a)
... some garbled characters ...
>>> np.save(sys.stdout, a)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<__array_function__ internals>", line 5, in save
...
TypeError: write() argument must be str, not bytes
原因是 accept bytes 参数而 accept str.因此,使用 array.tofile 写入不会导致任何错误,表明它没有调用方法。这引发了一个问题,它似乎不支持模式。对此感到抱歉。也许通过管道通过进程传输动态类型数据真的很难,但我听说在模块内部有一些方法可以在进程之间共享 RAM,这可能会有所帮助。sys.stdout.buffer.write()
sys.stdout.write()
sys.stdout
write()
np.save()
np.fromfile
dtype=object
ctype
提到我未能在终端(io.UnsupportedOperation: seek),但它在 PyCharm 的 python 控制台中运行良好。我对此一无所知。也许 PyCharm 的 python 控制台实际上也有 sys.stdin 的代理。
另外,它似乎是子过程。PIPE
具有最大缓冲区大小,因此无法传输渲染的图像。作为我的实验结果,将它们分成块无济于事。
评论
p.stdin.write('\n')