Skip to content

Commit 1988b8e

Browse files
committed
13.6小节完成
1 parent aaa9b9c commit 1988b8e

File tree

1 file changed

+72
-65
lines changed

1 file changed

+72
-65
lines changed

source/c13/p06_executing_external_command_and_get_its_output.rst

Lines changed: 72 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -5,92 +5,99 @@
55
----------
66
问题
77
----------
8-
You want to execute an external command and collect its output as a Python string.
8+
你想执行一个外部命令并以Python字符串的形式获取执行结果。
99

1010
|
1111
1212
----------
1313
解决方案
1414
----------
15-
Use the subprocess.check_output() function. For example:
15+
使用 ``subprocess.check_output()`` 函数。例如:
1616

17-
import subprocess
18-
out_bytes = subprocess.check_output(['netstat','-a'])
17+
.. code-block:: python
1918
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'])
2221
23-
out_text = out_bytes.decode('utf-8')
22+
这段代码执行一个指定的命令并将执行结果以一个字节字符串的形式返回。
23+
如果你需要文本形式返回,加一个解码步骤即可。例如:
2424

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
2726
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')
3328
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+
下面的例子捕获到错误并获取返回码:
3631

37-
out_bytes = subprocess.check_output(['cmd','arg1','arg2'],
38-
stderr=subprocess.STDOUT)
32+
.. code-block:: python
3933
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
4139
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`` 参数:
4642

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
5344
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)
5547
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()`` 函数来讲参数正确的用双引用引起来。
5968

6069
|
6170
6271
----------
6372
讨论
6473
----------
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

Comments
 (0)