从python调用shell脚本,需要一个文件而不将文件写入磁盘

时间:2012-11-22 11:40:17

标签: python pipe popen

为简化起见,我们假设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中,如果文件内容是由名为prog1的程序生成的,那么这将以这种方式解决:

$ cat <(prog1)

修改2

如果你不需要shell,那么Alfe提到的另一个选项更好,虽然问题仍然存在(即读取文件内容后进程没有完成)

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

3 个答案:

答案 0 :(得分: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在其上创建命名管道。我认为首先启动脚本然后写入管道应该可以工作......如果我成功了,我也会在这里写。

答案 1 :(得分:0)

摆弄一下,似乎关闭一侧的管道不会在关联的伪文件上生成eof / proc / self / fd /&lt;#&gt;儿童过程您是否尝试使用/ dev / stdin并简单地将输入传递给子进程的stdin?

答案 2 :(得分: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()