1

为简化起见,假设 shell 脚本是cat命令。在 shell 中,它通常会这样调用:

$ cat /some/path/myfile.txt

现在该文件将被动态创建并将其写入磁盘将是一个主要的性能损失,存在安全问题并增加多用户环境中的文件管理开销。该脚本无法修改,也无法从标准输入读取(cat只是一个工作示例)。

我试过这个:

import os
pin, pout = os.pipe()
pin, pout = os.fdopen(pin, 'r'), os.fdopen(pout,'w')

from subprocess import Popen
pout.write("test")
pout.flush()
p = Popen('cat /proc/self/fd/%s' % pout.fileno(), shell=True)

即使我关闭pout p.poll()仍然没有返回任何内容,表明该命令仍在等待来自管道的更多输入。

我怎样才能告诉命令没有更多的数据来自管道?有没有其他方法可以解决这个问题?

编辑

在 bash 中,如果文件内容是由名为prog1this 的程序生成的,将通过以下方式解决:

$ cat <(prog1)

编辑 2

如果您不需要外壳,那么 Alfe 提到的另一个选项会更好,尽管问题仍然存在(即读取文件内容后进程未完成)

#...same as before
p = Popen(['cat', '/dev/stdin'], stdin=pout)
4

3 回答 3

1

这就是我最后所做的,但并不好。

因为我正在开发 CentOS 并且遇到了问题(我在这里询问过:Python Popen can't open bash shell in CentOS/Red Hat)我无法使用execute='/bin/bash'这就是解决方案看起来有点不同的原因比问题。

我使用bash进程替换和here-documents将一些配置传递给进程:

file_contents = '...'
p = Popen(['/bin/bash', '-c', "cat <(cat<<'EOF_CFG'\n%s\nEOF_CFG\n)" % file_contents])

我现在正在考虑使用 tmpfs 在其上创建命名管道。我认为首先启动脚本然后写入管道应该可以工作......如果我成功了,我也会在这里写。

于 2012-11-23T13:01:14.637 回答
0

摆弄了一下,似乎关闭一侧的管道不会在子进程的关联伪文件 /proc/self/fd/<#> 上生成 eof。您是否尝试过使用 /dev/stdin 并将您的输入简单地通过管道传输到子进程的标准输入?

于 2012-11-22T15:56:55.460 回答
0

尝试为此使用命名管道。在其上,EOF 被正确传播:

$ mkfifo bla
$ python
from subprocess import Popen
p = Popen('cat bla', shell=True)
with file('bla', 'w') as f:
  f.write('test')

您也可以从 Python 动态创建命名管道,当然,只需使用os.mkfifo().

于 2012-11-23T13:32:50.777 回答