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

问题描述 投票:0回答:3

我将

subprocess.Popen
Python
一起使用,但我还没有遇到通过
&&
连接命令(即 foobar
Popen
bizbang)的优雅解决方案。

我可以这样做:

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)
python linux python-2.7 popen chaining
3个回答
9
投票

&&
是 shell 操作符,
Popen
默认不使用 shell。

如果您想使用 shell 功能,请在

shell=True
调用中使用
Popen
,但请注意,它会稍微慢一些/占用更多内存。

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

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"]])

0
投票

当命令是从外部输入构建时,强烈建议不要使用

shell=True
;因此链接多个命令的另一种方法是创建一个专用的批处理文件: import tempfile import platform is_windows = platform.system() == 'Windows' with tempfile.NamedTemporaryFile(suffix='.bat' if is_windows else '.sh', mode='w') as tmp: tmp.write('\n'.join(commands)) tmp.flush() execute_file = [tmp.name] if is_windows else ['/bin/bash', tmp.name] # Give execution permissions on unix platforms if not is_windows: subprocess.run(['chmod', 'u+x', tmp.name]) subprocess.run(execute_file)

© www.soinside.com 2019 - 2024. All rights reserved.