如何从Python代码中调用Shell脚本?

303

如何从Python代码中调用一个Shell脚本?

14个回答

365

subprocess模块将为您提供帮助。

显然微不足道的示例:

>>> import subprocess
>>> subprocess.call(['sh', './test.sh']) # Thanks @Jim Dennis for suggesting the []
0 
>>> 

test.sh是一个简单的shell脚本时,0是它这次运行的返回值。


14
注意:最好传递给subprocess.call()一个列表而不是一个字符串(请参见下面对Hugo24命令的示例和原因)。 - Jim Dennis
6
这会产生一个OSError错误:[Errno 13] 权限被拒绝。我的脚本不需要使用sudo运行。@Manoj Govindan - alper
11
使用参数:subprocess.call(['./test.sh','param1','param2']) - Henry
2
@alper 前往您放置脚本的文件夹并运行命令 chmod +x script.sh。注意:script.sh 是您脚本的占位符,请相应地进行替换。 - Tom J Muthirenthi
4
Python 3.5 中的 subprocess api 发生了变化。新的方法是 .run(args),而不是 call。 - Kévin Sanchez Lacroix
显示剩余4条评论

138

有一些方法可以使用os.popen()(已弃用)或整个subprocess模块,但这种方法更好。

import os
os.system(command)

是最简单的之一。


3
为什么这不是得票最高的答案?不需要导入一个模块难道不是更好的解决方案吗?这里必须有一些缺点吧? - boulder_ruby
15
使用 subprocess 可以管理输入/输出/错误管道。当您有多个参数时,使用 os.command() 需要创建整个命令行并转义特殊字符,而使用 subprocess 则只需要一个简单的参数列表。但对于简单任务,os.command() 可能已经足够了。 - Michał Niklas
4
引用自该链接:subprocess模块提供了更强大的功能,可以生成新进程并检索其结果;使用该模块比使用此函数更可取。 - Maximilian

57

如果您想将一些参数传递给您的Shell脚本,您可以使用方法shlex.split()

import subprocess
import shlex
subprocess.call(shlex.split('./test.sh param1 param2'))

在相同的文件夹中有test.sh:

#!/bin/sh
echo $1
echo $2
exit 0

输出:

$ python test.py 
param1
param2

1
这很优雅。 - caleb
如何将Python变量作为参数传递? - keerthi007
1
@keerthi007 subprocess.call(shlex.split(f"./test.sh param1 {your_python_var} param3")) - TDk

31
import os
import sys
假设test.sh是您要执行的Shell脚本。
os.system("sh test.sh")

19

我正在运行Python 3.5,但subprocess.call(['./test.sh'])对我无效。

我根据输出的用途给你三个解决方案。

1 - 调用脚本。你将在终端看到输出,输出是一个数字。

import subprocess 
output = subprocess.call(['test.sh'])

2-调用并将执行过程和错误信息输出到字符串中。如果没有打印(stdout),你看不到执行过程在终端中的输出。在Popen中使用Shell=True参数对我无效。


import subprocess
from subprocess import Popen, PIPE

session = subprocess.Popen(['test.sh'], stdout=PIPE, stderr=PIPE)
stdout, stderr = session.communicate()

if stderr:
    raise Exception("Error "+str(stderr))

3 - 调用脚本并将temp.txt中的echo命令转储到temp_file中

import subprocess
temp_file = open("temp.txt",'w')
subprocess.call([executable], stdout=temp_file)
with open("temp.txt",'r') as file:
    output = file.read()
print(output)

别忘了查看subprocess文档


2
注意不要在subprocess.call中使用stdout=PIPE或stderr=PIPE。如果子进程生成足够的输出以填满操作系统管道缓冲区,则该子进程将被阻塞,因为这些管道没有被读取。 - user9652688

19
使用如上所述的 subprocess 模块。 我像这样使用它:
subprocess.call(["notepad"])

17
注意:使用列表来调用子进程更加安全,因为它不需要通过 shell 进行解析/解释字符串(可能未经过滤)。列表中的第一项将作为可执行文件,其余项将作为参数传递。 - Jim Dennis

14

我知道这是一个老问题,但最近我偶然发现它并导致我产生了误导,因为自从Python 3.5以来,Subprocess API已经发生了变化。

执行外部脚本的新方法是使用 run 函数,该函数运行由参数描述的命令。等待命令完成,然后返回一个 CompletedProcess 实例。

import subprocess

subprocess.run(['./test.sh'])

8
如果脚本有多个参数:
#!/usr/bin/python

import subprocess
output = subprocess.call(["./test.sh","xyz","1234"])
print output

输出将给出状态码。如果脚本成功运行,它将返回0,否则返回非零整数。

podname=xyz  serial=1234
0

以下是test.sh shell脚本。
#!/bin/bash

podname=$1
serial=$2
echo "podname=$podname  serial=$serial"

4

Subprocess模块是启动子进程的好方法。您可以像这样使用它调用shell命令:

subprocess.call(["ls","-l"]);
#basic syntax
#subprocess.call(args, *)

您可以在此处查看其文档

如果您的脚本写在.sh文件或长字符串中,则可以使用os.system模块。这很简单,易于调用:

import os
os.system("your command here")
# or
os.system('sh file.sh')

该命令将运行脚本一次,直到完成,并阻塞直到退出。

你不需要导入sys吗? - ScottyBlades
不,你不需要;尝试打开Python shell并运行此代码片段。 - Descartes
嗨,Ankit。我需要一些帮助。假设example.sh文件在Oracle云基础设施中。如何在Python中调用/运行这样的example.sh文件?我需要连接到Oracle云,然后使用您在此处编写的脚本。您能否请编写附加代码(如何连接OCI中的example.sh文件)?谢谢。 - Sanky Ach

4

如果您的Shell脚本文件没有执行权限,请按以下方式进行操作。

import subprocess
subprocess.run(['/bin/bash', './test.sh'])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接