当预期数字列表时,Python子进程communic()产生None

时间:2015-12-24 22:21:58

标签: python subprocess

当我运行以下代码时

app.use('/', function(req, res, next) {
  console.log('do something here');
  next(); // Continue on to the next middleware/route handler
});
app.use(express.static(__dirname + '/mydir'));

myfile看起来像这样:

from subprocess import call, check_output, Popen, PIPE

gr = Popen(["grep", "'^>'", myfile], stdout=PIPE)
sd = Popen(["sed", "s/.*len=//"], stdin=gr.stdout)
gr.stdout.close()
out = sd.communicate()[0]
print out

我得到了

>name len=345
sometexthere
>name2 len=4523
someothertexthere
...
...

当预期输出是数字列表时:

None

我在终端中运行的相应命令是

345
4523
...
...

到目前为止,我尝试过以不同的方式进行转义和引用,例如在sed中转义斜线或为grep添加额外的引号,但组合的可能性很大。

我还考虑过在文件中读取并编写grep和sed的Python等价物,但文件非常大(我总是可以逐行读取),它总是在基于UNIX的系统上运行而且我是仍然好奇我犯了错误。

可能是那个

grep "^>" myfile | sed "s/.*len=//" > outfile

返回某种对象(而不是整数列表),其中None是类型?

我知道在简单的情况下我可以使用check_output获取输出:

sd.communicate()[0]

但不确定如何让它在更复杂的情况下工作,因为东西正在传输。

使用子流程获得预期结果的有效方法是什么?

4 个答案:

答案 0 :(得分:4)

  1. 不要在grep行中的^>附近放置单引号。这不是bash所以所有参数都将按字面意思传递给底层程序。
  2. 您需要将sd的标准重定向到PIPE。

答案 1 :(得分:4)

根据建议,您需要在第二个流程中stdout=PIPE并从"'^>'"中移除单引号:

gr = Popen(["grep", "^>", myfile], stdout=PIPE)
Popen(["sed", "s/.*len=//"], stdin=gr.stdout, stdout=PIPE)
......

但这可以简单地使用纯python和re

来完成
import re
r = re.compile("^\>.*len=(.*)$")
with open("test.txt") as f:
    for line in f:
        m =  r.search(line)
        if m:
            print(m.group(1))

哪个会输出:

345
4523

如果以>开头的行始终具有数字且数字始终位于len=之后,则您实际上不需要正则表达式:

with open("test.txt") as f:
    for line in f:
        if line.startswith(">"):
            print(line.rsplit("len=", 1)[1])

答案 2 :(得分:2)

您需要在第二次stdout来电时重定向Popen,否则输出将转到父进程标准输出,communicate将返回None

sd = Popen(["sed", "s/.*len=//"], stdin=gr.stdout, stdout=PIPE)

答案 3 :(得分:1)

Padraic Cunningham的回答是可以接受的

如何在命令行字符串中应用单引号

use shlex

import shlex
from subprocess import call, check_output, Popen, PIPE
gr = Popen(shlex.split("grep '^>' my_file"), stdout=PIPE)
sd = Popen(["sed", "s/.*len=//"], stdin=gr.stdout,stdout=PIPE)
gr.stdout.close()
out = sd.communicate()[0]
print out