|
5 | 5 | ----------
|
6 | 6 | 问题
|
7 | 7 | ----------
|
8 |
| -You want to execute an external command and collect its output as a Python string. |
| 8 | +你想执行一个外部命令并以Python字符串的形式获取执行结果。 |
9 | 9 |
|
10 | 10 | |
|
11 | 11 |
|
12 | 12 | ----------
|
13 | 13 | 解决方案
|
14 | 14 | ----------
|
15 |
| -Use the subprocess.check_output() function. For example: |
| 15 | +使用 ``subprocess.check_output()`` 函数。例如: |
16 | 16 |
|
17 |
| -import subprocess |
18 |
| -out_bytes = subprocess.check_output(['netstat','-a']) |
| 17 | +.. code-block:: python |
19 | 18 |
|
20 |
| -This runs the specified command and returns its output as a byte string. If you need to |
21 |
| -interpret the resulting bytes as text, add a further decoding step. For example: |
| 19 | + import subprocess |
| 20 | + out_bytes = subprocess.check_output(['netstat','-a']) |
22 | 21 |
|
23 |
| -out_text = out_bytes.decode('utf-8') |
| 22 | +这段代码执行一个指定的命令并将执行结果以一个字节字符串的形式返回。 |
| 23 | +如果你需要文本形式返回,加一个解码步骤即可。例如: |
24 | 24 |
|
25 |
| -If the executed command returns a nonzero exit code, an exception is raised. Here is |
26 |
| -an example of catching errors and getting the output created along with the exit code: |
| 25 | +.. code-block:: python |
27 | 26 |
|
28 |
| -try: |
29 |
| - out_bytes = subprocess.check_output(['cmd','arg1','arg2']) |
30 |
| -except subprocess.CalledProcessError as e: |
31 |
| - out_bytes = e.output # Output generated before error |
32 |
| - code = e.returncode # Return code |
| 27 | + out_text = out_bytes.decode('utf-8') |
33 | 28 |
|
34 |
| -By default, check_output() only returns output written to standard output. If you want |
35 |
| -both standard output and error collected, use the stderr argument: |
| 29 | +如果被执行的命令以非零码返回,就会抛出异常。 |
| 30 | +下面的例子捕获到错误并获取返回码: |
36 | 31 |
|
37 |
| -out_bytes = subprocess.check_output(['cmd','arg1','arg2'], |
38 |
| - stderr=subprocess.STDOUT) |
| 32 | +.. code-block:: python |
39 | 33 |
|
40 |
| -If you need to execute a command with a timeout, use the timeout argument: |
| 34 | + try: |
| 35 | + out_bytes = subprocess.check_output(['cmd','arg1','arg2']) |
| 36 | + except subprocess.CalledProcessError as e: |
| 37 | + out_bytes = e.output # Output generated before error |
| 38 | + code = e.returncode # Return code |
41 | 39 |
|
42 |
| -try: |
43 |
| - out_bytes = subprocess.check_output(['cmd','arg1','arg2'], timeout=5) |
44 |
| -except subprocess.TimeoutExpired as e: |
45 |
| - ... |
| 40 | +默认情况下,``check_output()`` 仅仅返回输入到标准输出的值。 |
| 41 | +如果你需要同时收集标准输出和错误输出,使用 ``stderr`` 参数: |
46 | 42 |
|
47 |
| -Normally, commands are executed without the assistance of an underlying shell (e.g., |
48 |
| -sh, bash, etc.). Instead, the list of strings supplied are given to a low-level system com‐ |
49 |
| -mand, such as os.execve(). If you want the command to be interpreted by a shell, |
50 |
| -supply it using a simple string and give the shell=True argument. This is sometimes |
51 |
| -useful if you’re trying to get Python to execute a complicated shell command involving |
52 |
| -pipes, I/O redirection, and other features. For example: |
| 43 | +.. code-block:: python |
53 | 44 |
|
54 |
| -out_bytes = subprocess.check_output('grep python | wc > out', shell=True) |
| 45 | + out_bytes = subprocess.check_output(['cmd','arg1','arg2'], |
| 46 | + stderr=subprocess.STDOUT) |
55 | 47 |
|
56 |
| -Be aware that executing commands under the shell is a potential security risk if argu‐ |
57 |
| -ments are derived from user input. The shlex.quote() function can be used to properly |
58 |
| -quote arguments for inclusion in shell commands in this case. |
| 48 | +如果你需要用一个超时机制来执行命令,使用 ``timeout`` 参数: |
| 49 | + |
| 50 | +.. code-block:: python |
| 51 | +
|
| 52 | + try: |
| 53 | + out_bytes = subprocess.check_output(['cmd','arg1','arg2'], timeout=5) |
| 54 | + except subprocess.TimeoutExpired as e: |
| 55 | + ... |
| 56 | +
|
| 57 | +通常来讲,命令的执行不需要使用到底层shell环境(比如sh、bash)。 |
| 58 | +一个字符串列表会被传递给一个低级系统命令,比如 ``os.execve()`` 。 |
| 59 | +如果你想让命令被一个shell执行,传递一个字符串参数,并设置参数 ``shell=True`` . |
| 60 | +有时候你想要Python去执行一个复杂的shell命令的时候这个就很有用了,比如管道流、I/O重定向和其他特性。例如: |
| 61 | + |
| 62 | +.. code-block:: python |
| 63 | +
|
| 64 | + out_bytes = subprocess.check_output('grep python | wc > out', shell=True) |
| 65 | +
|
| 66 | +需要注意的是在shell中执行命令会存在一定的安全风险,特别是当参数来自于用户输入时。 |
| 67 | +这时候可以使用 ``shlex.quote()`` 函数来讲参数正确的用双引用引起来。 |
59 | 68 |
|
60 | 69 | |
|
61 | 70 |
|
62 | 71 | ----------
|
63 | 72 | 讨论
|
64 | 73 | ----------
|
65 |
| -The check_output() function is the easiest way to execute an external command and |
66 |
| -get its output. However, if you need to perform more advanced communication with a |
67 |
| - |
68 |
| -subprocess, such as sending it input, you’ll need to take a difference approach. For that, |
69 |
| -use the subprocess.Popen class directly. For example: |
70 |
| - |
71 |
| -import subprocess |
72 |
| - |
73 |
| -# Some text to send |
74 |
| -text = b''' |
75 |
| -hello world |
76 |
| -this is a test |
77 |
| -goodbye |
78 |
| -''' |
79 |
| - |
80 |
| -# Launch a command with pipes |
81 |
| -p = subprocess.Popen(['wc'], |
82 |
| - stdout = subprocess.PIPE, |
83 |
| - stdin = subprocess.PIPE) |
84 |
| - |
85 |
| -# Send the data and get the output |
86 |
| -stdout, stderr = p.communicate(text) |
87 |
| - |
88 |
| -# To interpret as text, decode |
89 |
| -out = stdout.decode('utf-8') |
90 |
| -err = stderr.decode('utf-8') |
91 |
| - |
92 |
| -The subprocess module is not suitable for communicating with external commands |
93 |
| -that expect to interact with a proper TTY. For example, you can’t use it to automate tasks |
94 |
| -that ask the user to enter a password (e.g., a ssh session). For that, you would need to |
95 |
| -turn to a third-party module, such as those based on the popular “expect” family of tools |
96 |
| -(e.g., pexpect or similar). |
| 74 | +使用 ``check_output()`` 函数是执行外部命令并获取其返回值的最简单方式。 |
| 75 | +但是,如果你需要对子进程做更复杂的交互,比如给它发送输入,你得采用另外一种方法。 |
| 76 | +这时候可直接使用 ``subprocess.Popen`` 类。例如: |
| 77 | + |
| 78 | +.. code-block:: python |
| 79 | +
|
| 80 | + import subprocess |
| 81 | +
|
| 82 | + # Some text to send |
| 83 | + text = b''' |
| 84 | + hello world |
| 85 | + this is a test |
| 86 | + goodbye |
| 87 | + ''' |
| 88 | +
|
| 89 | + # Launch a command with pipes |
| 90 | + p = subprocess.Popen(['wc'], |
| 91 | + stdout = subprocess.PIPE, |
| 92 | + stdin = subprocess.PIPE) |
| 93 | +
|
| 94 | + # Send the data and get the output |
| 95 | + stdout, stderr = p.communicate(text) |
| 96 | +
|
| 97 | + # To interpret as text, decode |
| 98 | + out = stdout.decode('utf-8') |
| 99 | + err = stderr.decode('utf-8') |
| 100 | +
|
| 101 | +``subprocess`` 模块对于依赖TTY的外部命令不合适用。 |
| 102 | +例如,你不能使用它来自动化一个用户输入密码的任务(比如一个ssh会话)。 |
| 103 | +这时候,你需要使用到第三方模块了,比如基于著名的 ``expect`` 家族的工具(pexpect或类似的) |
0 commit comments