在subprocess.Popen中使用&&进行命令链?

10 投票
2 回答
15372 浏览
提问于 2025-04-17 19:26

我正在用 subprocess.PopenPython,但是我还没找到一个优雅的方法来把多个命令连接起来(比如 foobar&& bizbang)通过 Popen

我可以这样做:

p1 = subprocess.Popen(["mmls", "WinXP.E01"], stdout=subprocess.PIPE)
result = p1.communicate()[0].split("\n")
for line in result:
    script_log.write(line)

script_log.write("\n")

p1 = subprocess.Popen(["stat", "WinXP.E01"], stdout=subprocess.PIPE)
result = p1.communicate()[0].split("\n")
for line in result:
    script_log.write(line)

不过这样看起来真的不太好看(特别是当我通过 Popen 连续连接多个命令的时候)。


我希望能用尽可能少的命令块来实现这个输出。

not@work ~/ESI/lab3/images $ mmls WinXP.E01 && echo -e "\n" && stat WinXP.E01
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

     Slot    Start        End          Length       Description
00:  Meta    0000000000   0000000000   0000000001   Primary Table (#0)
01:  -----   0000000000   0000000062   0000000063   Unallocated
02:  00:00   0000000063   0020948759   0020948697   NTFS (0x07)
03:  -----   0020948760   0020971519   0000022760   Unallocated


  File: `WinXP.E01'
  Size: 4665518381  Blocks: 9112368    IO Block: 4096   regular file
Device: 14h/20d Inode: 4195953     Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/    nott)   Gid: ( 1000/    nott)
Access: 2013-03-16 23:20:41.901326579 -0400
Modify: 2013-03-04 10:05:50.000000000 -0500
Change: 2013-03-13 00:25:33.254684050 -0400
 Birth: -

有什么建议吗?

注意:我希望避免把这个输入到 subprocess.Popen 中。

p1 = subprocess.Popen(["mmls WinXP.E01 && echo -e '\n' && stat WinXP.E01"], stdout=subprocess.PIPE)

2 个回答

2

这样怎么样:

from subprocess import Popen, PIPE

def log_command_outputs(commands):
    processes = [Popen(cmd, stdout=PIPE) for cmd in commands]
    outputs = [proc.communicate()[0].split() for proc in processes]
    for output in outputs:
        for line in output:
            script_log.write(line)
        script_long.write("\n")

这个方法会同时开始执行多个命令,这样可能比一个一个执行要快一点(但可能不会快很多)。不过,由于communicate的调用是一个接一个的,所以任何输出很大的命令(超过管道的缓冲区)会一直等到轮到它清理的时候。

对于你给的命令链,你可以这样调用:

log_command_outputs([["mmls", "WinXP.E01"], ["stat", "WinXP.E01"]])
9

&& 是一个在命令行中用的操作符,而 Popen 默认情况下并不使用命令行。

如果你想使用命令行的功能,可以在调用 Popen 时加上 shell=True,但要注意,这样会稍微慢一些,而且占用更多内存。

p1 = subprocess.Popen(["mmls", "WinXP.E01", "&&", "echo", "-e", "\"\n\"", "&&", "stat", "WinXP.E01"],
                      stdout=subprocess.PIPE, shell=True)

撰写回答