是否可以使用相同的子进程命令按顺序执行任意数量的命令?
我需要每个命令在执行之前等待前一个命令完成,并且我需要它们都在同一个会话/shell中执行。我还需要在Python2.6和Python3.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())
如果这是不可能的,我应该采取什么方法来在同一个会话/shell中以同步顺序执行命令?
如果要在同一个会话/shell中一个接一个地执行多个命令,则必须启动一个shell并将所有命令(一次一个,后跟一个新行)馈送给它,然后在最后关闭管道。如果有些命令不是真正的进程,而是可以改变shell环境的shell命令,这是有意义的。
在Windows下使用Python2.7的示例:
要让这段代码在Linux下运行,您必须将
cmd.exe
替换为/bin/bash
,并可能将编码更改为utf8。对于Python 3,您必须对命令进行编码,可能还要对其输出进行解码,并在print中使用括号。
注意:这只会产生很小的效果。如果在关闭stdin管道之前有足够的输出来填充管道缓冲区,则此代码将死锁。一种更健壮的方法是让第二个线程读取命令的输出,以避免出现这种问题。
这与Serge Ballesta发布的答案相似,但并不完全相同。使用his进行异步执行,在异步执行中不关心结果。使用mine进行同步处理和结果收集。和他的回答一样,我在这里展示的是Windows解决方案-在Linux中运行bash进程,而不是在Windows中运行cmd。
用法详细信息:传递给
commands
方法的process.communicate
参数是一个以新行分隔的字符串。例如,如果您只是将批处理文件内容读入字符串,则可以这样运行它,因为它已经有了换行符。重要信息:字符串必须以换行结束
"\n"
。如果不这样做,最后的命令将无法执行。就像您在命令提示符中键入它,但没有在最后按enter
。但是,您将在返回的stdout的末尾看到一个神秘的More?
行。(这就是你遇到这种情况的原因)。process.communicate
按定义同步运行,并返回stdout和stderr消息(如果将它们定向到Popen构造函数中的subprocess.PIPE
)。当您以这种方式创建一个
cmd.exe
进程并向其传递一个字符串时,结果将与打开命令提示窗口并在其中输入命令完全相同。我是说真的。如果您对此进行测试,您将看到返回的stdout包含您的命令。(如果包含类似于执行批处理文件的@echo off
,这并不重要)。对那些关心“干净”标准输出结果的人的提示:
@echo off
不会禁止您的命令出现在此返回的字符串中,但它确实会删除额外的换行符,否则这些换行符会出现在该字符串中。(universal_newlines=True将另一组数据剥离)在命令中包含一个
@
符号前缀允许它们仍然执行。在“正常”批处理过程中,逐行“隐藏”命令。在这种情况下,它是一个安全而简单的标记,通过它可以找到要删除的标准输出行。(如果有人这么倾向的话)cmd.exe“header”将出现在您的输出中(显示Windows等的版本)。因为您可能想用
@echo off
来启动您的命令集,以删除额外的换行符,所以这也是一个找到标题行停止位置和命令/结果开始位置的好方法。最后,为了解决“大”输出填充管道并给您带来问题的问题(首先,我认为您需要大量数据返回才能解决问题),这比大多数人在其用例中遇到的问题都要多。其次,如果真的有问题,只需打开一个文件进行写入,并将该文件句柄(对文件对象的引用)传递给stdout/err,而不是
PIPE
。然后,对创建的文件执行任何所需的操作。一个可能的解决方案,看起来像是运行在同一个shell中:
注意-如果将命令作为字符串传递,那么shell必须为True 注意-这仅适用于linux,您可能需要在windows上找到类似的解决方法。
希望能有所帮助。
来自python文档-
相关问题 更多 >
编程相关推荐