fre*_*rik 13 python subprocess python-2.6 python-3.5
是否可以使用相同的子进程命令按顺序执行任意数量的命令?
我需要每个命令在执行之前等待前一个命令完成,我需要它们全部在同一个会话/ shell中执行.我还需要它在Python 2.6,Python 3.5中工作.我还需要subprocess命令才能在Linux,Windows和macOS中工作(这就是为什么我echo这里只使用命令作为示例).
请参阅下面的非工作代码:
import sys
import subprocess
cmds = ['echo start', 'echo mid', 'echo end']
p = subprocess.Popen(cmd=tuple([item for item in cmds]),
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
sys.stdout.flush()
print(">>> " + line.rstrip())
Run Code Online (Sandbox Code Playgroud)
如果这是不可能的,我应该采取哪种方法,以便在同一会话/ shell中以同步顺序执行我的命令?
这类似于 Serge Ballesta 发布的答案,但不完全相同。使用他的异步执行,你不关心结果。使用我的进行同步处理和结果收集。就像他的回答一样,我在这里展示了 Windows 解决方案 - 在 Linux 中运行 bash 进程而不是在 Windows 中运行 cmd。
from subprocess import Popen, PIPE
process = Popen( "cmd.exe", shell=False, universal_newlines=True,
stdin=PIPE, stdout=PIPE, stderr=PIPE )
out, err = process.communicate( commands )
Run Code Online (Sandbox Code Playgroud)
用法详细信息:commands这里传递给process.communicate方法的参数是一个换行符分隔的字符串。例如,如果您只是将批处理文件内容读入字符串,则可以以这种方式运行它,因为它已经有了换行符。
重要提示:您的字符串必须以换行符结尾"\n"。如果没有,则最终命令将无法执行。就像你在命令提示符中输入它但最后没有点击一样enter。但是,您会More?在返回的标准输出的末尾看到一条神秘的线。(如果您遇到这种情况,这就是原因)。
process.communicate 根据定义同步运行,并返回 stdout 和 stderr 消息(如果您将它们定向到 subprocess.PIPE在 Popen 构造函数中将)。
当您cmd.exe以这种方式创建一个进程,并将一个字符串传递给它时,结果将与您打开命令提示符窗口并在其中输入命令完全一样。我的意思是字面意思。如果您对此进行测试,您将看到返回的标准输出包含您的命令。(如果您包含一个@echo off在执行批处理文件时类似内容,则)。
给那些关心“干净”标准输出结果的人的提示:
@echo off不会禁止您的命令出现在这个返回的字符串中,但它会删除额外的换行符,否则它们会在那里找到。(universal_newlines=True 剥离另一组那些)
@在命令中包含符号前缀允许它们仍然执行。在“正常”批处理中,这是“隐藏”命令的逐行方式。在这种情况下,它是一个安全的简单标记,您可以通过它找到要删除的标准输出行。(如果有人这么倾向的话)
cmd.exe“标题”将出现在您的输出中(表示 Windows 的版本等)。由于您可能希望以 , 开始您的命令集@echo off,以删除额外的换行符,这也是查找标题行停止位置和命令/结果开始位置的好方法。
最后,为了解决对“大”输出填充管道并导致问题的担忧 - 首先,我认为您需要返回大量数据才能成为问题 - 比大多数人在他们的用例中遇到的要多。其次,如果真的是一个问题,只需打开一个文件进行写入并将该文件句柄(对文件对象的引用)传递给 stdout/err 而不是PIPE. 然后,对您创建的文件做任何您想做的事情。
如果要在同一会话/ shell中一个接一个地执行许多命令,则必须启动一个shell并向其提供所有命令,一次输入一个命令,然后换行,最后关闭管道。如果某些命令不是真正的进程,而是可以更改例如外壳环境的外壳命令,这是有道理的。
在Windows下使用Python 2.7的示例:
encoding = 'latin1'
p = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for cmd in cmds:
p.stdin.write(cmd + "\n")
p.stdin.close()
print p.stdout.read()
Run Code Online (Sandbox Code Playgroud)
要在Linux下运行此代码,您必须替换为utf8 cmd.exe,/bin/bash并且可能将其编码更改为utf8。
对于Python 3,您将必须对命令进行编码并可能对它们的输出进行解码,并在打印时使用括号。
当心:这仅适用于很少的输出。如果在关闭stdin管道之前有足够的输出来填充管道缓冲区,则此代码将死锁。一种更可靠的方法是让第二个线程读取命令的输出以避免该问题。
一种可能的解决方案看起来像是在同一个 shell 中运行:
subprocess.Popen('echo start;echo mid;echo end', shell=True)
Run Code Online (Sandbox Code Playgroud)
注意 - 如果您将命令作为字符串传递,那么 shell 必须为 True 注意 - 这仅适用于 Linux,您可能必须在 Windows 上找到类似的方法。
希望它会有所帮助。
来自 python 文档 -
在 shell=True 的 Unix 上,shell 默认为 /bin/sh。如果 args 是字符串,则该字符串指定要通过 shell 执行的命令。这意味着字符串的格式必须与在 shell 提示符下键入时完全相同。
| 归档时间: |
|
| 查看次数: |
27727 次 |
| 最近记录: |