如何在Python
脚本中调用外部命令(就像我在Unix shell或Windows命令提示符下键入它一样)?
答案 0 :(得分:4098)
查看标准库中的subprocess module:
import subprocess
subprocess.run(["ls", "-l"])
子流程与系统的优势在于它更灵活(您可以获取stdout,stderr,“真实”状态代码,更好的错误处理,等...)。
official documentation推荐子进程模块替代os.system():
子流程模块提供了更强大的工具来生成新流程并检索其结果;使用该模块比使用此函数[
os.system()
]更好。
子流程文档中的“Replacing Older Functions with the subprocess Module”部分可能有一些有用的配方。
旧版本的Python使用call:
import subprocess
subprocess.call(["ls", "-l"])
答案 1 :(得分:2755)
以下是调用外部程序的方法及其优缺点的摘要:
os.system("some_command with args")
将命令和参数传递给系统的shell。这很好,因为您实际上可以以这种方式一次运行多个命令并设置管道和输入/输出重定向。例如:
os.system("some_command < input_file | another_command > output_file")
但是,虽然这很方便,但您必须手动处理shell字符的转义,例如空格等。另一方面,这也允许您运行只是shell命令而不是外部程序的命令。请参阅the documentation。
stream = os.popen("some_command with args")
将执行与os.system
相同的操作,除了它为您提供了一个类似文件的对象,您可以使用该对象访问该进程的标准输入/输出。还有3种其他的popen变体,它们对i / o的处理方式略有不同。如果您将所有内容都作为字符串传递,那么您的命令将传递给shell;如果你将它们作为列表传递,那么你不必担心逃避任何事情。请参阅the documentation。
Popen
模块的subprocess
类。这是作为os.popen
的替代品,但由于其如此全面而具有稍微复杂的缺点。例如,你会说:
print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
而不是:
print os.popen("echo Hello World").read()
但很高兴在一个统一的类中使用所有选项而不是4个不同的popen函数。请参阅the documentation。
call
模块中的subprocess
函数。这基本上就像Popen
类一样,并且接受所有相同的参数,但它只是等待命令完成并为您提供返回代码。例如:
return_code = subprocess.call("echo Hello World", shell=True)
如果您使用的是Python 3.5或更高版本,则可以使用新的subprocess.run
函数,该函数与上述函数非常相似,但更灵活,并在返回CompletedProcess
对象时返回命令完成执行。
os模块还包含你在C程序中拥有的所有fork / exec / spawn函数,但我不建议直接使用它们。
subprocess
模块应该是您使用的模块。
最后请注意,对于所有将shell执行的最终命令作为字符串传递的方法,您负责转义它。 如果您传递的字符串的任何部分无法完全信任,则存在严重的安全隐患。例如,如果用户正在输入字符串的某些/任何部分。如果您不确定,请仅将这些方法与常量一起使用。为了给您一些暗示,请考虑以下代码:
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()
并想象用户输入的内容“我妈妈不爱我&amp;&amp; rm -rf /”这可能会删除整个文件系统。
答案 2 :(得分:305)
我通常使用:
import subprocess
p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
retval = p.wait()
您可以使用管道中的stdout
数据自由地执行所需操作。实际上,您可以简单地省略这些参数(stdout=
和stderr=
),它的行为就像os.system()
。
答案 3 :(得分:195)
从调用子进程中分离子进程的一些提示(在后台启动子进程)。
假设您想从CGI脚本启动一个长任务,那就是子进程应该比CGI脚本执行过程更长寿。
子流程模块docs的经典示例是:
import subprocess
import sys
# some code here
pid = subprocess.Popen([sys.executable, "longtask.py"]) # call subprocess
# some more code here
这里的想法是你不想在行'调用子进程'中等待,直到longtask.py完成。但目前尚不清楚在这个例子中“更多代码”之后会发生什么。
我的目标平台是freebsd,但开发工作是在windows上进行的,所以我先在Windows上遇到了问题。
在Windows(win xp)上,父进程在longtask.py完成其工作之前不会完成。这不是你想要的CGI脚本。问题不是Python特有的,在PHP社区中问题是一样的。
解决方案是将DETACHED_PROCESS Process Creation Flag传递给win API中的底层CreateProcess函数。 如果你碰巧安装了pywin32,你可以从win32process模块导入标志,否则你应该自己定义:
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
/ * UPD 2015.10.27 @eryksun在下面的评论中指出,语义正确的标志是CREATE_NEW_CONSOLE(0x00000010)* /
在freebsd上我们还有另一个问题:父进程完成后,它也会完成子进程。这也不是你想要的CGI脚本。一些实验表明问题似乎是在共享sys.stdout。工作解决方案如下:
pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
我没有检查其他平台上的代码,也不知道freebsd上的行为原因。如果有人知道,请分享您的想法。在Google上开始后台进程的Google搜索还没有任何亮点。
答案 4 :(得分:119)
我建议使用子进程模块而不是os.system,因为它会为你进行shell转义,因此更加安全:http://docs.python.org/library/subprocess.html
subprocess.call(['ping', 'localhost'])
答案 5 :(得分:118)
import os
cmd = 'ls -al'
os.system(cmd)
如果要返回命令的结果,可以使用os.popen
。但是,从版本2.6开始,这已经被弃用,而不是subprocess module,其他答案已经很好地解决了。
答案 6 :(得分:114)
import os
os.system("your command")
请注意,这是危险的,因为未清除该命令。我把它留给你去谷歌搜索关于'os'和'sys'模块的相关文档。有许多函数(exec *和spawn *)可以执行类似的操作。
答案 7 :(得分:72)
有许多不同的库允许您使用Python调用外部命令。对于每个库,我已经给出了描述并显示了调用外部命令的示例。我用作示例的命令是ls -l
(列出所有文件)。如果您想了解有关我列出的任何库的更多信息,并链接每个库的文档。
<强>来源:强>
以下是所有库:
希望这可以帮助您决定使用哪个库:)
<强>子强>
Subprocess允许您调用外部命令并将它们连接到它们的输入/输出/错误管道(stdin,stdout和stderr)。 Subprocess是运行命令的默认选择,但有时其他模块更好。
subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command
<强> OS 强>
os用于“依赖于操作系统的功能”。它还可以用于使用os.system
和os.popen
调用外部命令(注意:还有一个subprocess.popen)。 os将始终运行shell,对于不需要或不知道如何使用subprocess.run
的人来说,它是一个简单的替代方案。
os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output
<强> SH 强>
sh是一个子进程接口,它允许您像调用函数一样调用程序。如果要多次运行命令,这非常有用。
sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function
<强>铅强>
plumbum是一个用于“类似脚本”的Python程序的库。您可以像sh
中那样调用类似函数的程序。如果你想在没有shell的情况下运行管道,那么Plumbum很有用。
ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command
<强> Pexpect的强>
pexpect允许您生成子应用程序,控制它们并在其输出中查找模式。对于在Unix上期望tty的命令,这是一个更好的替代子进程。
pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')
<强>织物强>
fabric是一个Python 2.5和2.7库。它允许您执行本地和远程shell命令。 Fabric是在安全shell(SSH)中运行命令的简单替代方法
fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output
<强>特使强>
特使被称为“人类的子过程”。它被用作subprocess
模块周围的便利包装器。
r = envoy.run("ls -l") # Run command
r.std_out # get output
<强>命令强>
commands
包含os.popen
的包装函数,但它已从Python 3中删除,因为subprocess
是更好的选择。
编辑基于J.F. Sebastian的评论。
答案 8 :(得分:64)
我总是使用fabric
来表示:
from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )
但这似乎是一个很好的工具:sh
(Python subprocess interface)。
看一个例子:
from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
答案 9 :(得分:62)
也检查“pexpect”Python库。
它允许交互式控制外部程序/命令,甚至ssh,ftp,telnet等。您只需键入以下内容:
child = pexpect.spawn('ftp 192.168.0.24')
child.expect('(?i)name .*: ')
child.sendline('anonymous')
child.expect('(?i)password')
答案 10 :(得分:58)
如果您需要来自您正在呼叫的命令的输出, 然后你可以使用subprocess.check_output(Python 2.7 +)。
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
另请注意shell参数。
如果shell为
True
,则将通过shell执行指定的命令。如果您主要使用Python来提供它在大多数系统shell上提供的增强控制流,并且仍然希望方便地访问其他shell功能,例如shell管道,文件名通配符,环境变量扩展以及将〜扩展到用户家中,这将非常有用。目录。但请注意,Python本身提供了许多类似shell的功能的实现(特别是glob
,fnmatch
,os.walk()
,os.path.expandvars()
,os.path.expanduser()
和{ {1}})。
答案 11 :(得分:56)
在 使用subprocess module(Python 3):
import subprocess
subprocess.run(['ls', '-l'])
这是推荐的标准方式。但是,更复杂的任务(管道,输出,输入等)构造和编写可能会很繁琐。
关于Python版本的注意事项:如果您仍在使用Python 2,subprocess.call的工作方式类似。
ProTip:shlex.split可以帮助您解析run
,call
和其他subprocess
函数的命令,以防您不想要(或{你不能!)以列表的形式提供它们:
import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))
如果您不介意外部依赖项,请使用plumbum:
from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())
这是最好的subprocess
包装器。它是跨平台的,即它适用于Windows和类Unix系统。按pip install plumbum
安装。
另一个受欢迎的图书馆是sh:
from sh import ifconfig
print(ifconfig('wlan0'))
但是,sh
删除了Windows支持,所以它不像过去那样棒。按pip install sh
安装。
答案 12 :(得分:49)
这就是我运行命令的方式。此代码包含您需要的所有内容
from subprocess import Popen, PIPE
cmd = "ls -l ~/"
p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
print "Return code: ", p.returncode
print out.rstrip(), err.rstrip()
答案 13 :(得分:45)
subprocess.run
是推荐的方法as of Python 3.5。它更加一致,并提供与Envoy类似的易用性。 (虽然管道不是那么简单。请参阅this question for how。)
以下是the docs的一些示例。
运行流程:
>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
在失败的跑步中加注:
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
捕获输出:
>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')
我建议您尝试Envoy。它是子进程的包装器,而后者又是aims to replace较旧的模块和函数。特使是人类的子过程。
来自the readme的示例用法:
>>> r = envoy.run('git config', data='data to pipe in', timeout=2)
>>> r.status_code
129
>>> r.std_out
'usage: git config [options]'
>>> r.std_err
''
管道周围的东西:
>>> r = envoy.run('uptime | pbcopy')
>>> r.command
'pbcopy'
>>> r.status_code
0
>>> r.history
[<Response 'uptime'>]
答案 14 :(得分:37)
没有结果的输出:
import os
os.system("your command here")
输出结果:
import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
答案 15 :(得分:32)
https://docs.python.org/2/library/subprocess.html
...或者是一个非常简单的命令:
import os
os.system('cat testfile')
答案 16 :(得分:30)
还有Plumbum
>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad() # Notepad window pops up
u'' # Notepad window is closed by user, command returns
答案 17 :(得分:29)
os.system
没问题,但有点过时了。它也不是很安全。相反,请尝试subprocess
。 subprocess
不会直接调用sh,因此比os.system
更安全。
获取更多信息here。
答案 18 :(得分:28)
在Python中调用外部命令
简单,使用subprocess.run
,它返回一个CompletedProcess
对象:
>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)
从Python 3.5开始,文档建议subprocess.run:
调用子进程的推荐方法是对它可以处理的所有用例使用run()函数。对于更高级的用例,可以直接使用底层的Popen接口。
以下是最简单可能用法的示例 - 它完全按照要求执行:
>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)
run
等待命令成功完成,然后返回CompletedProcess
个对象。它可能会引发TimeoutExpired
(如果你给它一个timeout=
参数)或CalledProcessError
(如果它失败并且你通过了check=True
)。
正如您可能从上面的示例中推断的那样,默认情况下,stdout和stderr都会通过管道传输到您自己的stdout和stderr。
我们可以检查返回的对象并查看给出的命令和返回码:
>>> completed_process.args
'python --version'
>>> completed_process.returncode
0
如果您想捕获输出,可以将subprocess.PIPE
传递给相应的stderr
或stdout
:
>>> cp = subprocess.run('python --version',
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
>>> cp.stderr
b'Python 3.6.1 :: Anaconda 4.4.0 (64-bit)\r\n'
>>> cp.stdout
b''
(我觉得有趣而且有点违反直觉,版本信息会被放到stderr而不是stdout。)
可以轻松地从手动提供命令字符串(如问题建议)到提供以编程方式构建的字符串。 不要以编程方式构建字符串。这是一个潜在的安全问题。假设你不相信输入,那就更好了。
>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n This is indented.\r\n'
注意,只有args
才能在位置上传递。
以下是来源中的实际签名,如help(run)
所示:
def run(*popenargs, input=None, timeout=None, check=False, **kwargs):
popenargs
和kwargs
被赋予Popen
构造函数。 input
可以是一串字节(或unicode,如果指定编码或universal_newlines=True
),它将被传送到子进程的stdin。
该文档比我更好地描述了timeout=
和check=True
:
超时参数传递给Popen.communicate()。如果超时 到期后,子进程将被终止并等待。该 子进程发生后,将重新引发TimeoutExpired异常 终止。
如果check为true,并且进程以非零退出代码退出,则a 将引发CalledProcessError异常。属性 异常保存参数,退出代码以及stdout和stderr if 他们被抓获了。
这个check=True
的示例比我想出的更好:
>>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
这是一个扩展的签名,如文档中所示:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)
请注意,这表示只应按位置传递args列表。所以将剩下的参数作为关键字参数传递。
使用Popen
代替?我很难根据论据单独找到用例。但是,直接使用Popen
会让您访问其方法,包括poll
,'send_signal','terminate'和'wait'。
以下是the source中给出的Popen
签名。我认为这是对信息的最精确封装(与help(Popen)
相对):
def __init__(self, args, bufsize=-1, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
shell=False, cwd=None, env=None, universal_newlines=False,
startupinfo=None, creationflags=0,
restore_signals=True, start_new_session=False,
pass_fds=(), *, encoding=None, errors=None):
但更多信息是the Popen
documentation:
subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None)
在新流程中执行子程序。在POSIX上,该类使用 os.execvp() - 执行子程序的行为。在Windows上, 该类使用Windows CreateProcess()函数。争论的论点 Popen如下。
了解Popen
上的其余文档将留给读者练习。
答案 19 :(得分:25)
可以这么简单:
import os
cmd = "your command"
os.system(cmd)
答案 20 :(得分:25)
答案 21 :(得分:20)
这里有另一个区别,以前没有提到过。
subprocess.Popen
执行&lt; command&gt;作为子进程。就我而言,我需要执行文件&lt; a&gt;需要与另一个程序通信,&lt; b&gt;。
我尝试了子进程,执行成功了。然而&lt; b&gt;无法与&lt; a&gt;进行通信。 当我从终端运行时,一切正常。
还有一个: (注意:kwrite的行为与其他应用程序不同。如果您使用Firefox尝试以下操作,结果将不同。)
如果您尝试os.system("kwrite")
,程序流将冻结,直到用户关闭kwrite。为了克服这个问题,我尝试了os.system(konsole -e kwrite)
。这个时间程序继续流动,但kwrite成为控制台的子进程。
任何人都运行kwrite不是子进程(即在系统监视器中它必须出现在树的最左边)。
答案 22 :(得分:20)
我倾向于将subprocess与shlex一起使用(以处理引用字符串的转义):
>>> import subprocess, shlex
>>> command = 'ls -l "/your/path/with spaces/"'
>>> call_params = shlex.split(command)
>>> print call_params
["ls", "-l", "/your/path/with spaces/"]
>>> subprocess.call(call_params)
答案 23 :(得分:20)
subprocess.check_call
很方便。它会在任何错误上抛出异常。
答案 24 :(得分:19)
我非常喜欢shell_command的简单性。它建立在子进程模块之上。
以下是文档中的示例:
>>> from shell_command import shell_call
>>> shell_call("ls *.py")
setup.py shell_command.py test_shell_command.py
0
>>> shell_call("ls -l *.py")
-rw-r--r-- 1 ncoghlan ncoghlan 391 2011-12-11 12:07 setup.py
-rw-r--r-- 1 ncoghlan ncoghlan 7855 2011-12-11 16:16 shell_command.py
-rwxr-xr-x 1 ncoghlan ncoghlan 8463 2011-12-11 16:17 test_shell_command.py
0
答案 25 :(得分:19)
os.system
不允许您存储结果,因此如果您想将结果存储在某个列表中,或subprocess.call
有效。
答案 26 :(得分:16)
无耻的插件,我为此写了一个库:P https://github.com/houqp/shell.py
现在它基本上是popen和shlex的包装器。它还支持管道命令,因此您可以在Python中更轻松地链接命令。所以你可以做以下事情:
ex('echo hello shell.py') | "awk '{print $2}'"
答案 27 :(得分:15)
在Linux下,如果你想调用一个独立执行的外部命令(将在python脚本终止后继续运行),你可以使用一个简单的队列task spooler或at命令
任务假脱机程序的示例:
import os
os.system('ts <your-command>')
有关任务假脱机程序(ts
)的说明:
您可以设置要运行的并发进程数(&#34; slots&#34;):
ts -S <number-of-slots>
安装ts
并不需要管理员权限。您可以使用简单的make
从源代码下载并编译它,将其添加到您的路径中并完成。
答案 28 :(得分:14)
在Windows中,您只需导入ip_list
模块并通过调用subprocess
,subprocess.Popen()
和subprocess.Popen().communicate()
运行外部命令,如下所示:
subprocess.Popen().wait()
输出:
# Python script to run a command line
import subprocess
def execute(cmd):
"""
Purpose : To execute a command and return exit status
Argument : cmd - command to execute
Return : exit_code
"""
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(result, error) = process.communicate()
rc = process.wait()
if rc != 0:
print "Error: failed to execute command:", cmd
print error
return result
# def
command = "tasklist | grep python"
print "This process detail: \n", execute(command)
答案 29 :(得分:13)
您可以使用Popen,然后您可以检查程序的状态:
from subprocess import Popen
proc = Popen(['ls', '-l'])
if proc.poll() is None:
proc.kill()
答案 30 :(得分:12)
运行任何命令并获得结果的最简单方法:
from commands import getstatusoutput
try:
return getstatusoutput("ls -ltr")
except Exception, e:
return None
答案 31 :(得分:12)
Invoke 是Python(2.7和3.4+)任务执行工具和库。它为运行Shell命令提供了一个干净的高级API
>>> from invoke import run
>>> cmd = "pip install -r requirements.txt"
>>> result = run(cmd, hide=True, warn=True)
>>> print(result.ok)
True
>>> print(result.stdout.splitlines()[-1])
Successfully installed invocations-0.13.0 pep8-1.5.7 spec-1.3.1
答案 32 :(得分:11)
以下是我的两分钱:在我看来,这是处理外部命令时的最佳做法......
这些是execute方法的返回值......
pass, stdout, stderr = execute(["ls","-la"],"/home/user/desktop")
这是执行方法......
def execute(cmdArray,workingDir):
stdout = ''
stderr = ''
try:
try:
process = subprocess.Popen(cmdArray,cwd=workingDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1)
except OSError:
return [False, '', 'ERROR : command(' + ' '.join(cmdArray) + ') could not get executed!']
for line in iter(process.stdout.readline, b''):
try:
echoLine = line.decode("utf-8")
except:
echoLine = str(line)
stdout += echoLine
for line in iter(process.stderr.readline, b''):
try:
echoLine = line.decode("utf-8")
except:
echoLine = str(line)
stderr += echoLine
except (KeyboardInterrupt,SystemExit) as err:
return [False,'',str(err)]
process.stdout.close()
returnCode = process.wait()
if returnCode != 0 or stderr != '':
return [False, stdout, stderr]
else:
return [True, stdout, stderr]
答案 33 :(得分:11)
从openstack neutron中获取网络ID:
#!/usr/bin/python
import os
netid= "nova net-list | awk '/ External / { print $2 }'"
temp=os.popen(netid).read() /* here temp also contains new line (\n) */
networkId=temp.rstrip()
print(networkId)
输出 nova net-list
+--------------------------------------+------------+------+
| ID | Label | CIDR |
+--------------------------------------+------------+------+
| 431c9014-5b5d-4b51-a357-66020ffbb123 | test1 | None |
| 27a74fcd-37c0-4789-9414-9531b7e3f126 | External | None |
| 5a2712e9-70dc-4b0e-9281-17e02f4684c9 | management | None |
| 7aa697f5-0e60-4c15-b4cc-9cb659698512 | Internal | None |
+--------------------------------------+------------+------+
输出打印(networkId)
27a74fcd-37c0-4789-9414-9531b7e3f126
答案 34 :(得分:8)
通常,我对外部命令使用以下函数,这对于长时间运行的进程尤其方便。下面的方法 tails处理输出 ,而正在运行并返回输出,引发异常,如果进程失败。
如果使用流程上的 poll()方法完成流程,就会出现。
textInput: Any;
您可以这样调用它:
import subprocess,sys
def exec_long_running_proc(command, args):
cmd = "{} {}".format(command, " ".join(str(arg) if ' ' not in arg else arg.replace(' ','\ ') for arg in args))
print(cmd)
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# Poll process for new output until finished
while True:
nextline = process.stdout.readline().decode('UTF-8')
if nextline == '' and process.poll() is not None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
output = process.communicate()[0]
exitCode = process.returncode
if (exitCode == 0):
return output
else:
raise Exception(command, exitCode, output)
答案 35 :(得分:7)
这是调用外部命令并返回或打印命令的输出:
Python Subprocess check_output适用于
使用参数运行命令并将其输出作为字节字符串返回。
import subprocess
proc = subprocess.check_output('ipconfig /all')
print proc
答案 36 :(得分:7)
在Python中调用外部命令
调用外部命令的一种简单方法是使用os.system(...)
。此函数返回命令的退出值。但缺点是我们没有获得stdout和stderr。
ret = os.system('some_cmd.sh')
if ret != 0 :
print 'some_cmd.sh execution returned failure'
在后台用Python调用外部命令
subprocess.Popen
为运行外部命令提供了更大的灵活性,而不是使用os.system
。我们可以在后台启动命令并等待它完成。之后我们可以得到stdout和stderr。
proc = subprocess.Popen(["./some_cmd.sh"], stdout=subprocess.PIPE)
print 'waiting for ' + str(proc.pid)
proc.wait()
print 'some_cmd.sh execution finished'
(out, err) = proc.communicate()
print 'some_cmd.sh output : ' + out
在后台调用Python中长时间运行的外部命令,并在一段时间后停止
我们甚至可以使用subprocess.Popen
在后台启动一个长时间运行的进程,并在完成任务后的某个时间终止它。
proc = subprocess.Popen(["./some_long_run_cmd.sh"], stdout=subprocess.PIPE)
# Do something else
# Now some_long_run_cmd.sh exeuction is no longer needed, so kill it
os.system('kill -15 ' + str(proc.pid))
print 'Output : ' proc.communicate()[0]
答案 37 :(得分:7)
作为一个例子(在Linux中):
import subprocess
subprocess.run('mkdir test.dir', shell=True)
这会在当前目录中创建test.dir。 请注意,这也有效:
import subprocess
subprocess.call('mkdir test.dir', shell=True)
使用os.system的等效代码是:
import os
os.system('mkdir test.dir')
最佳做法是使用subprocess而不是os,.run优于.call。 您需要了解的有关子流程的所有信息都是here。 另请注意,所有Python文档都可以从here下载。我下载了打包为.zip的PDF文件。我之所以提到这一点是因为在tutorial.pdf(第81页)中对os模块进行了很好的概述。此外,它还是Python程序员的权威资源。
答案 38 :(得分:7)
使用:
import subprocess
p = subprocess.Popen("df -h", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")
它提供了更好的输出,更容易使用:
['Filesystem Size Used Avail Use% Mounted on',
'/dev/sda6 32G 21G 11G 67% /',
'none 4.0K 0 4.0K 0% /sys/fs/cgroup',
'udev 1.9G 4.0K 1.9G 1% /dev',
'tmpfs 387M 1.4M 386M 1% /run',
'none 5.0M 0 5.0M 0% /run/lock',
'none 1.9G 58M 1.9G 3% /run/shm',
'none 100M 32K 100M 1% /run/user',
'/dev/sda5 340G 222G 100G 69% /home',
'']
答案 39 :(得分:7)
有两种突出的方式可以使用Python执行Shell命令。以下两个示例都说明了如何使用Python获取当前工作目录(pwd
)的名称。您可以使用任何其他Unix命令代替pwd
。
1.>第一种方法:一个人可以使用python中的os模块,然后使用system()函数在Python中执行shell命令。
import os
os.system('pwd')
输出:
/Users/siddharth
1.>第二种方法:另一种方法是使用subprocess模块和call()函数。
import subprocess
subprocess.call('pwd')
输出:
/Users/siddharth
答案 40 :(得分:7)
添加到讨论中,如果您使用Python控制台,则可以从IPython调用外部命令。在IPython提示符下,您可以通过前缀'!'来调用shell命令。您还可以将Python代码与shell结合使用,并将shell脚本的输出分配给Python变量。
例如:
In [9]: mylist = !ls
In [10]: mylist
Out[10]:
['file1',
'file2',
'file3',]
答案 41 :(得分:6)
在Python中运行外部命令的方法有很多种, 而且他们都有自己的优缺点。
我和我的同事一直在编写Python系统管理工具,因此我们需要运行大量外部命令,有时您希望它们以异步方式阻塞或运行,超时,每秒更新等等。
还有不同的方法来处理返回代码和错误, 并且您可能想要解析输出,并提供新的输入(以expect样式)。或者您需要重定向stdin,stdout和stderr以在不同的tty中运行(例如,在使用屏幕时)。
所以你可能不得不围绕外部命令编写很多包装器。所以这是我们编写的可以处理的Python模块 几乎你想要的任何东西,如果没有,它非常灵活,所以你可以很容易地扩展它:
https://github.com/hpcugent/vsc-base/blob/master/lib/vsc/utils/run.py
答案 42 :(得分:5)
答案 43 :(得分:5)
最坏的情况:
在大多数情况下,您只需要一小段这样的代码:
void (*print)(const struct point*);
简洁明了。
import subprocess import shlex source = "test.txt" destination = "test_copy.txt" base = "cp {source} {destination}'" cmd = base.format(source=source, destination=destination) subprocess.check_call(shlex.split(cmd))
运行带有参数的命令并等待 命令完成。
subprocess.check_call
使用类似shell的语法分割字符串cmd
其余情况:
如果这对于某些特定命令不起作用,则很可能是您 command-line interpreters遇到了问题。操作系统选择了不适合您的程序类型的默认程序,或者在系统可执行路径上找不到合适的程序。
示例:
在Unix系统上使用重定向运算符
shlex.split
如The Zen of Python中所述:显式优于 隐式
因此,如果使用Python> = 3.6函数,它将看起来像这样:
input_1 = "input_1.txt"
input_2 = "input_2.txt"
output = "merged.txt"
base_command = "/bin/bash -c 'cat {input} > {output}'"
base_command.format(input_1, output=output_1)
subprocess.check_call(shlex.split(base_command))
base_command.format(input_1, output=output_2)
subprocess.check_call(shlex.split(base_command))
答案 44 :(得分:5)
有多种方法可以从Python调用外部命令。有一些带有好帮手功能的功能和模块可以使它变得非常容易。但其中最推荐的是Subprocess
模块。
import subprocess as s
s.call(["command.exe","..."])
Call函数将启动外部进程,传递一些命令行参数,然后等待其完成。完成后,您将继续执行。调用函数中的参数通过列表传递。列表中的第一个参数通常是可执行文件形式的命令,而列表中的后续参数则是您要传递的参数。
如果您已经在Windows中从命令行调用了进程,那么您将意识到经常需要引用参数。您需要在引号周围加上引号,如果有空格,则存在反斜线,并且存在一些复杂的规则,但是您可以使用subprocess
模块在python中避免很多,因为它是一个列表,每个项目众所周知这是一个独特的功能,而python可以为您正确报价。
最后,在列表之后,有许多可选参数,其中之一是shell,如果将shell equals设置为true,则将像在命令提示符下键入命令一样运行命令
s.call(["command.exe","..."], shell=True)
这使您可以访问管道等功能,可以重定向到文件,可以在一件事中调用多个命令。
还有一件事,如果您的脚本依赖于成功的进程,那么您要检查结果,并可以使用check call helper函数检查结果。
s.check_call(...)
它与调用函数完全相同,它采用相同的参数,采用相同的列表,您可以传入任何其他参数,但是它将等待函数完成。如果该函数的退出代码不是零,则它将通过python脚本中的异常。
最后,如果您想更严格地控制Popen
构造函数,该构造函数也来自subprocess
模块。它也采用与incall和check_call函数相同的参数,但是它返回一个代表正在运行的进程的对象。
p=s.Popen("...")
它不等待正在运行的进程完成,也不打算立即引发任何异常,但是它为您提供了一个对象,使您可以执行诸如等待其完成,与之通信,可以重定向等操作标准输入,如果要在其他地方显示输出,则为标准输出。
答案 45 :(得分:5)
自2018年6月27日发布的 Python 3.7.0(https://docs.python.org/3/whatsnew/3.7.html)起,您可以以最强大而又简单的方式获得所需的结果。该答案旨在以简短的方式向您展示各种选项的基本摘要。有关深入的答案,请参阅其他答案。
os.system(...)
的最大优势在于它的简单性。 subprocess
更好并且仍然易于使用,尤其是从 Python 3.5 开始。
import subprocess
subprocess.run("ls -a", shell=True)
注意: 这是您问题的确切答案-运行命令
像在外壳上一样
如果可能,请除去外壳程序的开销并直接运行命令(需要列表)。
import subprocess
subprocess.run(["help"])
subprocess.run(["ls", "-a"])
在列表中传递程序参数。 不要在包含空格的参数中使用\"
进行转义。
以下代码说明一切:
import subprocess
result = subprocess.run(["ls", "-a"], capture_output=True, text=True)
if "stackoverflow-logo.png" in result.stdout:
print("You're a fan!")
else:
print("You're not a fan?")
result.stdout
是所有正常程序输出,不包括错误。阅读result.stderr
以获取它们。
capture_output=True
-打开捕获。否则result.stderr
和result.stdout
将是None
。可从 Python 3.7 获得。
text=True
-在 Python 3.7 中添加的便捷参数,它将接收到的二进制数据转换为您可以轻松使用的Python字符串。
做 如果result.returncode == 127:print(“程序由于某种奇怪的原因而失败”) elif result.returncode == 0:print(“程序成功”) 否则:print(“程序意外失败”)
如果只想检查程序是否成功(返回码== 0)并抛出异常,则有一个更方便的功能:
result.check_returncode()
但是它是Python,因此有一个更方便的参数check
可以自动为您执行相同的操作:
result = subprocess.run(..., check=True)
您可能希望所有程序输出都在stdout内部,甚至包括错误。为此,请运行
result = subprocess.run(..., stderr=subprocess.STDOUT)
result.stderr
将是None
,而result.stdout
将包含所有内容。
shell=False
需要一个列表参数。但是,您可以使用shlex自己分割参数字符串。
import subprocess
import shlex
subprocess.run(shlex.split("ls -a"))
就是这样。
遇到这个问题时,您刚开始使用Python的机会很高。让我们看一些常见的问题。
FileNotFoundError:[错误2]没有这样的文件或目录:'ls -a':'ls -a'
您正在运行没有shell=True
的子流程。使用列表(["ls", "-a"]
)或设置shell=True
。
TypeError:[...]无类型[...]
检查是否已设置capture_output=True
。
TypeError:需要一个类似字节的对象,而不是[...]
您始终会从程序中接收字节结果。如果要像普通字符串一样使用它,请设置text=True
。
subprocess.CalledProcessError:命令'[...]'返回非零退出状态1。
您的命令未成功运行。您可以禁用返回码检查或检查实际程序的有效性。
TypeError: init ()有一个意外的关键字参数[...]
您可能正在使用3.7.0之前的Python版本;将其更新为最新版本。否则,此StackOverflow帖子中还会有其他答案,向您显示较早的替代解决方案。
答案 46 :(得分:5)
对于Python 3.5+,建议您使用run function from the subprocess module。这将返回一个CompletedProcess
对象,您可以从中轻松获取输出以及返回代码。
from subprocess import PIPE, run
command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
答案 47 :(得分:4)
有很多方法可以调用命令。
如果and.exe
需要两个参数。在cmd中我们可以调用sample.exe
使用它:
and.exe 2 3
并在屏幕上显示5
。
如果我们使用Python脚本来调用and.exe
,我们应该这样做..
os.system(cmd,...)
os.system(("and.exe" + " " + "2" + " " + "3"))
os.popen(cmd,...)
os.popen(("and.exe" + " " + "2" + " " + "3"))
subprocess.Popen(cmd,...)
subprocess.Popen(("and.exe" + " " + "2" + " " + "3"))
这太难了,所以我们可以用空格加入cmd:
import os
cmd = " ".join(exename,parameters)
os.popen(cmd)
答案 48 :(得分:4)
使用Popen
Python模块的subprocess
函数是运行Linux命令的最简单方法。在那里,Popen.communicate()
函数将为您的命令输出。例如
import subprocess
..
process = subprocess.Popen(..) # Pass command and arguments to the function
stdout, stderr = process.communicate() # Get command output and error
..
答案 49 :(得分:4)
我写了一个小库来帮助解决这个用例:
https://pypi.org/project/citizenshell/
可以使用
安装pip install citizenshell
然后按如下方式使用:
from citizenshell import sh
assert sh("echo Hello World") == "Hello World"
您可以将stdout与stderr分开,并按如下所示提取退出代码:
result = sh(">&2 echo error && echo output && exit 13")
assert result.stdout() == ["output"]
assert result.stderr() == ["error"]
assert result.exit_code() == 13
很酷的事情是,您不必等待底层shell退出就可以开始处理输出:
for line in sh("for i in 1 2 3 4; do echo -n 'It is '; date +%H:%M:%S; sleep 1; done", wait=False)
print ">>>", line + "!"
将打印行,因为wait = False
>>> It is 14:24:52!
>>> It is 14:24:53!
>>> It is 14:24:54!
>>> It is 14:24:55!
中找到
答案 50 :(得分:4)
一种简单的方法是使用os模块:
import os
os.system('ls')
或者您也可以使用子流程模块
import subprocess
subprocess.check_call('ls')
如果您希望将结果存储在变量中,请尝试:
import subprocess
r = subprocess.check_output('ls')
答案 51 :(得分:4)
from subprocess import call
# using list
call(["echo", "Hello", "world"])
# single string argument varies across platforms so better split it
call("echo Hello world".split(" "))
答案 52 :(得分:4)
如果您正在编写Python shell脚本并在系统上安装了IPython,则可以使用bang magic在IPython中运行命令:
!ls
filelist = !ls
答案 53 :(得分:2)
我建议使用以下方法'run',它将帮助我们将STDOUT,STDERR和退出状态作为字典;这个调用者可以通过'run'方法读取字典返回,以了解进程的实际状态。
def run (cmd):
print "+ DEBUG exec({0})".format(cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True)
(out, err) = p.communicate()
ret = p.wait()
out = filter(None, out.split('\n'))
err = filter(None, err.split('\n'))
ret = True if ret == 0 else False
return dict({'output': out, 'error': err, 'status': ret})
#end
答案 54 :(得分:2)
由于某些答案与以前的python版本有关或正在使用os.system
模块,因此我为打算在subprocess
中使用python 3.5+
的类似我的人发布了此答案。以下是在Linux上为我完成的技巧:
import subprocess
#subprocess.run() returns a completed process object that can be inspected
c = subprocess.run(["ls", "-ltrh"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(c.stdout.decode('utf-8'))
如documentation中所述,PIPE
值是字节序列,为正确显示它们,应考虑解码。对于更高版本的python,text=True
和encoding='utf-8'
被添加到subprocess.run()
的kwarg中。
上述代码的输出为:
total 113M
-rwxr-xr-x 1 farzad farzad 307 Jan 15 2018 vpnscript
-rwxrwxr-x 1 farzad farzad 204 Jan 15 2018 ex
drwxrwxr-x 4 farzad farzad 4.0K Jan 22 2018 scripts
.... # some other lines
答案 55 :(得分:2)
我编写了一个包装器来处理错误并重定向输出和其他东西。
import shlex
import psutil
import subprocess
def call_cmd(cmd, stdout=sys.stdout, quiet=False, shell=False, raise_exceptions=True, use_shlex=True, timeout=None):
"""Exec command by command line like 'ln -ls "/var/log"'
"""
if not quiet:
print("Run %s", str(cmd))
if use_shlex and isinstance(cmd, (str, unicode)):
cmd = shlex.split(cmd)
if timeout is None:
process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, shell=shell)
retcode = process.wait()
else:
process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, shell=shell)
p = psutil.Process(process.pid)
finish, alive = psutil.wait_procs([p], timeout)
if len(alive) > 0:
ps = p.children()
ps.insert(0, p)
print('waiting for timeout again due to child process check')
finish, alive = psutil.wait_procs(ps, 0)
if len(alive) > 0:
print('process {} will be killed'.format([p.pid for p in alive]))
for p in alive:
p.kill()
if raise_exceptions:
print('External program timeout at {} {}'.format(timeout, cmd))
raise CalledProcessTimeout(1, cmd)
retcode = process.wait()
if retcode and raise_exceptions:
print("External program failed %s", str(cmd))
raise subprocess.CalledProcessError(retcode, cmd)
您可以这样称呼它:
cmd = 'ln -ls "/var/log"'
stdout = 'out.txt'
call_cmd(cmd, stdout)
答案 56 :(得分:2)
经过一些研究,我有以下代码,对我来说效果很好。它基本上实时打印stdout和stderr。希望它可以帮助其他需要它的人。
stdout_result = 1
stderr_result = 1
def stdout_thread(pipe):
global stdout_result
while True:
out = pipe.stdout.read(1)
stdout_result = pipe.poll()
if out == '' and stdout_result is not None:
break
if out != '':
sys.stdout.write(out)
sys.stdout.flush()
def stderr_thread(pipe):
global stderr_result
while True:
err = pipe.stderr.read(1)
stderr_result = pipe.poll()
if err == '' and stderr_result is not None:
break
if err != '':
sys.stdout.write(err)
sys.stdout.flush()
def exec_command(command, cwd=None):
if cwd is not None:
print '[' + ' '.join(command) + '] in ' + cwd
else:
print '[' + ' '.join(command) + ']'
p = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
)
out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))
err_thread.start()
out_thread.start()
out_thread.join()
err_thread.join()
return stdout_result + stderr_result
答案 57 :(得分:2)
import subprocess
p = subprocess.run(["ls", "-ltr"], capture_output=True)
print(p.stdout.decode(), p.stderr.decode())
答案 58 :(得分:1)
Eli上面描述的subprocess module非常强大,但是进行沼泽标准系统调用并检查其输出的语法是不必要的延长。
进行系统调用的最简单方法是使用commands module(仅限Linux)。
> import commands
> commands.getstatusoutput("grep matter alice-in-wonderland.txt")
(0, "'Then it doesn't matter which way you go,' said the Cat.")
元组中的第一项是进程的返回码。第二项是其标准输出(和标准错误,合并)。
Python开发人员已经“弃用”了命令模块,但这并不意味着你不应该使用它。只是他们不再开发它了,这没关系,因为它已经很完美了(虽然它很小但很重要)。
答案 59 :(得分:1)
os.popen()
是执行命令的最简单,最安全的方法。您可以执行在命令行上运行的任何命令。此外,您还可以使用os.popen().read()
您可以这样做:
import os
output = os.popen('Your Command Here').read()
print (output)
列出当前目录中所有文件的示例:
import os
output = os.popen('ls').read()
print (output)
# Outputs list of files in the directory
答案 60 :(得分:1)
Python 3.5 +
import subprocess
p = subprocess.run(["ls", "-ltr"], capture_output=True)
print(p.stdout.decode(), p.stderr.decode())
答案 61 :(得分:1)
Sultan是用于此目的的最新包装。提供有关管理用户权限和添加有用的错误消息的一些技巧。
window.addEventListener('load', e => {
console.log("page loaded");
let canvas = document.getElementById('pcb');
let context = canvas.getContext("2d");
let img = new Image();
img.onload = function() {
context.drawImage(
img,
800, 0,
800, 800,
0, 0,
800, 800
);
console.log("drawImage fired!");
};
img.src = "/i/sprite-comp.png";
});
答案 62 :(得分:0)
如果您不在命令中使用用户输入,则可以使用
from os import getcwd
from subprocess import check_output
from shlex import quote
def sh(command):
return check_output(quote(command), shell=True, cwd=getcwd(), universal_newlines=True).strip()
并将其用作
branch = sh('git rev-parse --abbrev-ref HEAD')
shell=True
将产生一个外壳,因此您可以使用管道和类似外壳的东西sh('ps aux | grep python')
。这对于运行硬编码的命令并处理其输出非常方便。 universal_lines=True
确保以字符串形式而不是二进制形式返回输出。
cwd=getcwd()
将确保命令在与解释器相同的工作目录下运行。对于git命令来说,就像上面的git分支名称示例一样,这很方便。
一些食谱
sh('free -m').split('\n')[1].split()[1]
sh('df -m /').split('\n')[1].split()[4][0:-1]
sum(map(float, sh('ps -ef -o pcpu').split('\n')[1:])
但这对于从文档中输入的用户并不安全:
安全注意事项¶
与其他一些popen函数不同,此实现永远不会 隐式调用系统外壳。这意味着所有字符, 包括外壳元字符,可以安全地传递给孩子 流程。如果通过shell = True显式调用了shell,则为 应用程序有责任确保所有空白和 适当引用元字符以避免注入外壳 漏洞。
当使用shell = True时,shlex.quote()函数可用于 在字符串中正确地转义空格和外壳元字符 将用于构造Shell命令。
即使在外壳命令上使用用户输入时,即使使用shlex.quote()
也可以保持一点偏执。一种选择是使用硬编码命令来获取一些常规输出并通过用户输入进行过滤。无论如何,使用shell=False
都会确保仅执行您要执行的确切过程,否则会出现No such file or directory
错误。
另外,对shell=True
的性能也有一些影响,根据我的测试,它似乎比shell=False
(默认值)慢20%。
In [50]: timeit("check_output('ls -l'.split(), universal_newlines=True)", number=1000, globals=globals())
Out[50]: 2.6801227919995654
In [51]: timeit("check_output('ls -l', universal_newlines=True, shell=True)", number=1000, globals=globals())
Out[51]: 3.243950183999914
答案 63 :(得分:-1)
您还可以使用subprocess.getoutput()
模块中的{strong> Legacy Shell Invocation Functions 的subprocess.getstatusutput()
和commands
,即:
subprocess.getstatusoutput(cmd)
在shell中执行
exitcode
返回(output
,cmd
)。
subprocess.getoutput(cmd)
在外壳中返回执行
stdout
的输出(stderr
和cmd
)。
答案 64 :(得分:-3)
我将此用于3.6 +
import subprocess
def execute(cmd):
"""
Purpose : To execute a command and return exit status
Argument : cmd - command to execute
Return : result, exit_code
"""
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(result, error) = process.communicate()
rc = process.wait()
if rc != 0:
print ("Error: failed to execute command: ", cmd)
print (error.rstrip().decode("utf-8"))
return result.rstrip().decode("utf-8"), serror.rstrip().decode("utf-8")
# def