如何使用Python运行bash脚本?
如果您使用Linux,那么您肯定会喜欢shell命令。
如果您使用Python,那么您可能已经尝试自动化一些东西。这是节省时间的一种方式。您可能还有一些bash脚本来自动化一些东西。
Python比bash更方便编写脚本。与bash脚本相比,管理Python脚本更容易。一旦bash脚本变得越来越复杂,您会发现很难维护它。
但是如果您已经有了想要使用Python运行的bash脚本怎么办?
有没有办法在Python中执行bash命令和脚本?
是的,Python有一个内置模块叫做subprocess,用于在Python脚本中执行命令和脚本。让我们详细看看如何在Python脚本中执行bash命令和脚本。
执行Bash命令
如您可能已经看到的,模块subprocess用于执行bash命令和脚本。它提供了不同的方法和类。
主要有一个方法和一个类要了解的是subprocess模块。它们是run和Popen。这两个帮助我们在Python脚本中执行bash命令。让我们逐个看看。
subprocess.run()
方法subprocess.run()
将以列表形式接收一个字符串作为位置参数。这是强制性的,因为它包含了bash命令和其参数。列表中的第一项是命令名称,其余项是命令的参数。
让我们来看一个快速示例。
import subprocess
subprocess.run(["ls"])
上面的脚本会列出当前工作目录中的所有项目。上面的脚本中没有命令的参数。我们只提供了bash命令。我们可以为ls
命令提供其他参数,如-l
,-a
,-la
等。
让我们来看一个带有命令参数的快速示例。
import subprocess
subprocess.run(["ls", "-la"])
上面的命令显示包括隐藏文件和权限在内的所有文件。我们提供了la
参数,该参数显示了文件和目录的额外信息以及隐藏文件。
在编写命令时,我们可能会犯一些错误。根据错误会引发异常。如果希望捕获并稍后使用它们怎么办?是的,我们可以使用关键字参数stderr来实现。
让我们来看一个示例。
import subprocess
result = subprocess.run(["cat", "sample.txt"], stderr=subprocess.PIPE, text=True)
print(result.stderr)
确保您的工作目录中没有名为sample.txt的文件。关键字参数stderr的值为PIPE,它将错误以对象的形式返回。我们可以使用相同的名称稍后访问它。关键字参数text告诉输出应该是一个字符串。
类似地,我们可以使用stdout关键字参数来捕获命令的输出。
import subprocess
result = subprocess.run(["echo", "Hello, World!"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
print(result.stdout)
subprocess.run() – input
您可以使用input关键字参数为命令提供输入。我们将以字符串格式提供输入。因此,我们需要将关键字参数text设置为True
。默认情况下,它以字节形式接收输入。
让我们看一个示例。
import subprocess
subprocess.run(["python3", "add.py"], text=True, input="2 3")
在上面的程序中,Python脚本add.py 将接受两个数字作为输入。我们使用input 关键字参数将输入传递给Python脚本。
subprocess.Popen()
类subprocess.Popen() 比方法subprocess.run()更高级。它提供了更多的选项来执行命令。我们将创建一个subprocess.Popen() 的实例,并将其用于诸如了解命令执行状态、获取输出、提供输入等的各种操作。
类subprocess.Popen()有几个需要了解的方法。让我们逐个查看它们以及代码示例。
wait
它用于等待命令执行完成。在wait
方法之后编写的Python脚本的下一行不会执行,直到前一个命令执行完成。让我们看一个例子。
“`python
import subprocess
process = subprocess.Popen([“ls”, “-la”])
print(“Completed!”)
“`
观察输出。你会发现打印出了Completed! 的消息,而命令执行之前。我们可以使用wait
方法避免这种情况。让我们等待命令的完成。
“`python
import subprocess
process = subprocess.Popen([“ls”, “-la”])
process.wait()
print(“Completed!”)
“`
如果你看到上面代码的输出,你会意识到wait
确实起作用。在命令执行完成后,打印语句才会执行。
communicate
方法communicate
用于获取输出、错误和给命令输入。它返回一个包含输出和错误的元组。让我们看一个例子。
“`python
import subprocess
process = subprocess.Popen([“echo”, “Hello, World!”], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
result = process.communicate()
print(result)
“`
subprocess.Popen() – input
我们不能直接将输入传递给类Popen
。我们需要使用关键字参数stdin 将输入传递给命令。类Popen
的实例将为我们提供一个stdin
对象。它有一个称为write
的方法,用于向命令输入数据。
如前所述,默认情况下,它将以类似字节的对象的形式接收输入。因此,在创建Popen
的实例时,请不要忘记将关键字参数text 设置为True
。
让我们看一个例子。
“`python
import subprocess
process = subprocess.Popen([“python3”, “add.py”], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
process.stdin.write(“2 3”)
process.stdin.close()
print(process.stdout.read())
“`
poll
方法poll
用于检查命令是否执行完成。如果命令仍在执行,此方法将返回None
。让我们看一个例子。
“`python
import subprocess
process = subprocess.Popen([‘ping', ‘-c 5', ‘yaoweibin.com'], stdout=subprocess.PIPE, text=True)
while True:
output = process.stdout.readline()
if output:
print(output.strip())
result = process.poll()
if result is not None:
break
“`
在上面的代码中,我们使用了带有5个请求的ping
命令。有一个无限循环,它在命令执行完成之前进行迭代。我们使用poll
方法来检查命令执行的状态。如果poll
方法返回的代码不是None
,则表示执行完成。然后退出无限循环。
执行Bash脚本
我们已经看到了两种执行命令的方式。现在,让我们看看如何在Python脚本中执行Bash脚本。
subprocess 有一个叫做call的方法。这个方法用于执行Bash脚本。该方法返回Bash脚本的退出代码。Bash脚本的默认退出代码为0。让我们看一个例子。
创建一个名为practice.sh的Bash脚本,内容如下。
#!/bin/bash
echo "Hello, World!"
exit 1
现在,编写一个Python脚本来执行上述Bash脚本。
import subprocess
exit_code = subprocess.call('./practice.sh')
print(exit_code)
当你运行上述Python脚本时,你将得到以下输出。
Hello, World!
1
结论
我们已经看到了如何在Python中执行Bash命令和脚本。你可以使用它们来更高效地自动化工作。
Happy Coding 👨💻