叫一个外部命令在蟒蛇
-
01-07-2019 - |
题
怎么我可以叫一个外部命令(如果我输入它的Unix壳或命令提示的)从内 Python
剧本吗?
解决方案
看看 子流程模块 在标准图书馆:
import subprocess
subprocess.run(["ls", "-l"])
优点 子流程 与 系统 是,它是更灵活的(你可以获得标准输出,stderr,"实际"地位代码、更好的错误处理,等等...)。
的 官方文件 建议的 子流程 模块通过替代的操作系统。系统():
的 子流程 模块提供更强大的设施,为产生新的进程和检索他们的结果;使用该模块是最好使用这一功能[
os.system()
].
该"更换较旧的功能与电子流程模块"部分 子流程 文件可能有一些有用的食谱。
旧版本的蟒蛇使用呼叫:
import subprocess
subprocess.call(["ls", "-l"])
其他提示
这里有一个摘要的方式,以呼吁外部程序和优点和缺点:
os.system("some_command with args")
通过命令和参数系统的外壳。这是不错的,因为你可以实际运行多个命令在一次以这种方式,并设立了管道和输入/输出重新定向。例如:os.system("some_command < input_file | another_command > output_file")
然而,虽然这是方便的,你必须手工处理逃脱壳的人物,如空间,等等。另一方面,这还可以让你运行命令,这是简单的命令并没有实际外部程序。看看 该文件.
stream = os.popen("some_command with args")
会做同样的事情os.system
除了它给你一个类似文件的对象,可用于访问的标准输入/输出对这一进程。有3个其他的变种popen所有处理的i/o略有不同。如果你通过一切,因为一串,那么你的命令传递给壳;如果你通过它们作为一个列表那你不需要担心逃避任何事情。看看 该文件.的
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功能。看看 该文件.
的
call
从功能subprocess
模块。这是基本上只是喜欢的Popen
类,并采取所有的相同的论点,但它只是等待,直到该命令完成,并给你回代码。例如:return_code = subprocess.call("echo Hello World", shell=True)
看看 该文件.
如果你在Python3.5或之后,可以使用的新的
subprocess.run
功能,这是一个很像上面,但甚至更加灵活和返回CompletedProcess
目时命令完成执行。Os模块,也有的所有叉/exec/产卵的功能,你必须在一C节目,但是我不建议使用他们直接。
的 subprocess
模块也许应该是你用什么。
最后请注意,所有方法在哪里你通过最终的命令来执行的由外壳作为一串,你是负责逃避它。 有严重的安全影响 如果任何一部分的字符串通,不能完全信任。例如,如果一个用户进入某一/任意字符串的一部分。如果你不确定,只使用这些方法与常数。给你一个暗示的影响考虑这个代号:
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()
并且想象一下,用户进入的东西"是我的妈妈不爱我&&rm-rf/"这可能删除整个文件系统。
我通常使用:
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()
.
一些提示关于分离的儿童过程中从一个叫(原子过程中背景)。
假设你要开始一个长期的任务从一个CGI-script,这是儿童过程中应该活的时间比CGI-script执行过程。
经典的例子流程模块文件是:
import subprocess
import sys
# some code here
pid = subprocess.Popen([sys.executable, "longtask.py"]) # call subprocess
# some more code here
这里的想法是,你不想等在线呼叫子流程,直到的longtask.py 完成。但不清楚会发生什么后的行一些更多的代码这里的例子。
我的目标的平台是freebsd,但发展上的窗户,所以我面临的问题,在windows第一次。
On windows(赢xp),父母进程将不会完成,直到longtask.py 已完成其工作。这不是你想要什么在CGI-script.问题不是具体到蟒蛇,在PHP社会问题都是相同的。
该方案是要通过DETACHED_PROCESS 工艺创作的标志 基础CreateProcess功能赢得API。如果你已经安装pywin32你可以进口标志从win32process模块,否则你应该确定它自己:
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
/* UPD2015.10.27 @eryksun在下面的评论注意到,在语义上正确的标志是CREATE_NEW_CONSOLE(0x00000010)*/
Freebsd上,我们有另一个问题:当父母过程完成后,它完成儿童的进程。这不是你想要什么在CGI-script。一些实验表明,问题似乎是在共享sys.stdout。和工作方案如下:
pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
我没有检查的码在其他平台上并不知道原因的行为在freebsd。如果有人知道,请分享你的想法。谷歌上搜索开始背景过程中蟒蛇不会摆脱任何光呢。
我建议使用子进程模块,而不是操作系统。系统,因为它并壳逃避你因此更安全: http://docs.python.org/library/subprocess.html
subprocess.call(['ping', 'localhost'])
import os
os.system("your command")
注意,这是危险的,因为该命令不是清除。我把它留给你谷歌的有关文件上的'os'和'系'模块。还有一堆的职能(exec*和产卵*),将做类似的事情。
有很多不同的图书馆,让你可以呼吁外部命令蟒蛇。每个图书馆我已经给一个说明和示例叫一个外部命令。命令我作为例 ls -l
(名单的所有文件)。如果你想要找出更多有关的任何图书馆我已经列出,并相联的文件为他们每个人。
资料来源:
- 子流程: https://docs.python.org/3.5/library/subprocess.html
- shlex: https://docs.python.org/3/library/shlex.html
- 操作系统: https://docs.python.org/3.5/library/os.html
- sh: https://amoffat.github.io/sh/
- 铅: https://plumbum.readthedocs.io/en/latest/
- pexpect: https://pexpect.readthedocs.io/en/stable/
- 布: http://www.fabfile.org/
- 特使: https://github.com/kennethreitz/envoy
- 命令: https://docs.python.org/2/library/commands.html
这些是所有的图书馆:
希望这会帮助你做一个决定在其图书馆的使用:)
子流程
子流程允许你打电话的外部命令和将它们连接到他们输入/输出/错误的管道(stdin,stdout,并stderr)。子流程是默认选择的运行命令,但是有时其他模块。
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.system
和 os.popen
(注:还有一个子流程.popen).os会一直运行的壳是一个简单的替代方法的人不需要或不知道如何使用 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
铅
铅是一个图书馆为"脚本"的蟒蛇的程序。你可以呼吁程序等的职能作为在 sh
.铅是有用的,如果你想要运行一个管道没有外壳。
ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command
pexpect
pexpect可以让你生孩子应用程序、控制他们发现模式,在他们的输出。这是一个更好的替代子进程的命令,预期tty在Unix。
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')
织物
布是蟒蛇2.5和2.7图书馆。它可以让你执行当地和远程的外壳的命令。简单的替代运行命令在一个安全的外壳(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
, 但它已经从3,因为蟒蛇 subprocess
是一个更好的选择。
编辑依据的是约翰塞巴斯蒂安的评论。
我总是用 fabric
为此喜欢的东西:
from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )
但是,这似乎是一个很好的工具: sh
(Python子流程界面).
看一个例子:
from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
检查"pexpect"蟒库,也是。
它允许进行交互式控制的外部程序/命令,甚至ssh,ftp,telnet,等等。你可以只类型是这样的:
child = pexpect.spawn('ftp 192.168.0.24')
child.expect('(?i)name .*: ')
child.sendline('anonymous')
child.expect('(?i)password')
如果你需要的输出命令你叫, 然后你可以用 子流程.check_output (Python2.7+).
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
还注意 外壳 参数。
如果壳
True
,指定的命令将执行通过的外壳。这可能是有用的,如果您使用的是蟒的主要是为了加强控制流程,它提供了最有系统的炮弹,并仍然希望便利其他外壳的特征,例如壳管道、文件通配符的环境变量扩展,并扩大~一户家目录。然而,注意蟒蛇本身提供实现的许多壳类似的功能(特别,glob
,fnmatch
,os.walk()
,os.path.expandvars()
,os.path.expanduser()
, ,shutil
).
与标准图书馆
的 使用 子流程模块 (Python3):
import subprocess
subprocess.run(['ls', '-l'])
这是所建议的标准的方式。然而,更为复杂的任务(管道、输出、输入,等等。) 可能是繁琐的建造和写。
注意到在蟒蛇的版本:如果你还在使用蟒蛇2, 子流程.呼叫 在一类似的方式。
巧合的是 shlex.分裂 可以帮助你分析的命令 run
, call
, 和其他的 subprocess
职能的情况下,你不想(或者,你不能!) 他们提供的形式列出了:
import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))
与外部的依赖
如果你不介意外部的依赖,使用 铅:
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
.
这是我执行我的命令。这个代码拥有你需要的一切都漂亮多了
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()
更新:
subprocess.run
是的推荐方法 作为Python3.5 如果你的代码不需要保持兼容性与早期蟒蛇的版本。它的更加一致,并提供相似的便于使用作为特使。(管道不是那么简单,虽然。看看 这个问题对于如何.)
这里是一些例子 文档.
运行一个过程:
>>> 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')
原来的回答:
我建议你尝试 特使.这是一个包子流程,这反过来 旨在替换 旧模块的功能。特使是子流程对于人类。
例使用情况 自述:
>>> 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'>]
没有输出结果:
import os
os.system("your command here")
与输出结果:
import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
https://docs.python.org/2/library/subprocess.html
...或者对于一个非常简单的命令:
import os
os.system('cat testfile')
还有 铅
>>> 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
os.system
是好的,但是,种类的日期。这也不很安全。相反,尝试 subprocess
. subprocess
不叫sh直接因此更安全 os.system
.
获得更多的信息 在这里,.
叫一个外部命令在蟒蛇
简单的使用 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)
为什么?
作为Python3.5,该文件建议 子流程.运行:
建议的方法来调子过程是使用的运行()功能,对所有使用的情况下,它可以处理。对于更高级的使用情况,基础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 and stderr都获得通过管道输送到你自己的stdout and stderr默认。
我们可以检查返回的目的和看到的命令是给予和returncode:
>>> 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。)
通过一个指令列表中的
一个可能很容易移动,从手工提供一个命令string(喜欢的问题,建议)提供一串建的编程方式。 不建立串的编程方式。 这是一个潜在的安全问题。这是更好地假设你不信任的输入。
>>> 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.沟通().如果超时 期满时,孩子的过程会被杀死和等待。的 TimeoutExpired例外,将重新提出后的儿童过程中具有 终止。
如果检查是真实的,并且处理退出一个非零的出口码, CalledProcessError异常会提出。属性, 异常举行的论点,出口码,并stdout and stderr如果 他们被抓获。
和这个例子 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
而不是?我会努力寻找使用情况的基础上的论点孤独。直接使用 Popen
然而,给你访问到它的方法,包括 poll
,'send_signal','终止','等等'.
这里的 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):
但更多的信息是 的 Popen
文档:
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,这类使用 操作系统。execvp()行为的执行儿童计划。在窗户, 这类使用的Windows CreateProcess()function.的参数 Popen如下。
理解剩余的文件 Popen
将保留为一个运动对于读者。
它可以是这样简单:
import os
cmd = "your command"
os.system(cmd)
使用os模块
import os
os.system("your command")
例如:
import os
os.system("ifconfig")
subprocess.check_call
是便利的如果你不想要试验返回值。它将引发一个例外的任何错误。
还有另一个差别在这里哪个是不是提到以前。
subprocess.Popen
执行 <command> 作为一个子流程.在我的情况下,我需要执行的文件 <a> ,这需要与另一个计划 <b>.
我尝试子流程和执行是否成功。但是 <b> 可以不通 <a>.一切正常,当我运行的终端。
一个更:(注:kwrite的行为不同于其他应用程序。如果你试试下面有Firefox,结果将不会是一样的。)
如果你试图 os.system("kwrite")
, ,程序流程的冻结,一直到用户关闭kwrite.要克服,我想代替 os.system(konsole -e kwrite)
.这段时间计划继续流动,但是kwrite成为子进程的控制台。
任何人行kwrite不是一个子进程(即在系统监测它必须出现在最左边的树)。
os.system
不允许商店的结果,所以如果你想要储存的结果,在一些列表或什么的 subprocess.call
工程。
我很喜欢 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
无耻的插头,我写了一个图书馆为此:P https://github.com/houqp/shell.py
它基本上是一个包装popen和shlex。它还支持管道命令,因此可以命令更容易在蟒蛇。所以你可以不喜欢的东西:
ex('echo hello shell.py') | "awk '{print $2}'"
你可以使用Popen,然后你可以检查程序的状况:
from subprocess import Popen
proc = Popen(['ls', '-l'])
if proc.poll() is None:
proc.kill()
检查了 子流程.Popen.