Skip to content

Commit 02eb20a

Browse files
committed
Merge pull request yidao620c#27 from tylinux/master
翻译了第12章第1节,顺便修改了第11章第1节的一些错别字
2 parents 62d71cb + 792a445 commit 02eb20a

File tree

2 files changed

+128
-142
lines changed

2 files changed

+128
-142
lines changed

source/c11/p01_interact_with_http_services_as_client.rst

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
----------
66
问题
77
----------
8-
你需要以客户端的方式通过HTTP协议方位多种服务。例如,下载数据或者与基于REST的API进行交互。
8+
你需要通过HTTP协议以客户端的方式访问多种服务。例如,下载数据或者与基于REST的API进行交互。
99

1010
----------
1111
解决方案
@@ -32,7 +32,7 @@
3232
u = request.urlopen(url+'?' + querystring)
3333
resp = u.read()
3434
35-
如果你需要使用POST方法在请求主体中发送查询参数,可以将参数编码后作为可选参数提供给 ``URLopen()`` 函数,就像这样:
35+
如果你需要使用POST方法在请求主体中发送查询参数,可以将参数编码后作为可选参数提供给 ``urlopen()`` 函数,就像这样:
3636

3737
.. code-block:: python
3838
@@ -99,7 +99,7 @@
9999
# Decoded text returned by the request
100100
text = resp.text
101101
102-
关于requests库,一个值得一提的特性就是它能以多种凡是从请求中返回响应结果的内容。从上面的代码来看, ``resp.text`` 带给我们的是以Unicode解码的响应文本。但是,如果去访问 ``resp.content`` ,就会得到原始的二进制数据。另一方面,如果访问 ``resp.json`` ,那么就会得到JSON格式的响应内容。
102+
关于requests库,一个值得一提的特性就是它能以多种方式从请求中返回响应结果的内容。从上面的代码来看, ``resp.text`` 带给我们的是以Unicode解码的响应文本。但是,如果去访问 ``resp.content`` ,就会得到原始的二进制数据。另一方面,如果访问 ``resp.json`` ,那么就会得到JSON格式的响应内容。
103103

104104
下面这个示例利用 ``requests`` 库发起一个HEAD请求,并从响应中提取出一些HTTP头数据的字段:
105105

@@ -145,7 +145,7 @@
145145
----------
146146
讨论
147147
----------
148-
对于真的很简单HTTP客户端代码,用内置的 ``urllib`` 模块通常就足够了。但是,如果你要做的不仅仅只是简单的GET或POST请求,那就真的不能在依赖它的功能了。这时候就是第三方模块比如 ``requests`` 大显身手的时候了。
148+
对于真的很简单HTTP客户端代码,用内置的 ``urllib`` 模块通常就足够了。但是,如果你要做的不仅仅只是简单的GET或POST请求,那就真的不能再依赖它的功能了。这时候就是第三方模块比如 ``requests`` 大显身手的时候了。
149149

150150
例如,如果你决定坚持使用标准的程序库而不考虑像 ``requests`` 这样的第三方库,那么也许就不得不使用底层的 ``http.client`` 模块来实现自己的代码。比方说,下面的代码展示了如何执行一个HEAD请求:
151151

@@ -180,7 +180,7 @@
180180
# From here. You can access more pages using opener
181181
...
182182
183-
坦白说,所有的这些操作在 ``equests`` 库中都变得简单的多。
183+
坦白说,所有的这些操作在 ``requests`` 库中都变得简单的多。
184184

185185
在开发过程中测试HTTP客户端代码常常是很令人沮丧的,因为所有棘手的细节问题都需要考虑(例如cookies、认证、HTTP头、编码方式等)。要完成这些任务,考虑使用httpbin服务(http://httpbin.org)。这个站点会接收发出的请求,然后以JSON的形式将相应信息回传回来。下面是一个交互式的例子:
186186

@@ -198,6 +198,6 @@
198198
{'name': 'Dave', 'n': '37'}
199199
>>>
200200
201-
在要同一个真正的站点进行交互前,先在 httpbin.org 这样的万展上做实验常常是可取的办法。尤其是当我们面对3次登录失败就会关闭账户这样的风险时尤为有用(不要尝试自己编写HTTP认证客户端来登录你的银行账户)。
201+
在要同一个真正的站点进行交互前,先在 httpbin.org 这样的网站上做实验常常是可取的办法。尤其是当我们面对3次登录失败就会关闭账户这样的风险时尤为有用(不要尝试自己编写HTTP认证客户端来登录你的银行账户)。
202202

203203
尽管本节没有涉及, ``request`` 库还对许多高级的HTTP客户端协议提供了支持,比如OAuth。 ``requests`` 模块的文档(http://docs.python-requests.org)质量很高(坦白说比在这短短的一节的篇幅中所提供的任何信息都好),可以参考文档以获得更多地信息。

source/c12/p01_start_stop_thread.rst

Lines changed: 122 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -5,148 +5,134 @@
55
----------
66
问题
77
----------
8-
You want to create and destroy threads for concurrent execution of code.
9-
10-
|
8+
你要为需要并发执行的代码创建/销毁线程
119

1210
----------
1311
解决方案
1412
----------
15-
The threading library can be used to execute any Python callable in its own thread. To
16-
do this, you create a Thread instance and supply the callable that you wish to execute
17-
as a target. Here is a simple example:
18-
19-
# Code to execute in an independent thread
20-
import time
21-
def countdown(n):
22-
while n > 0:
23-
print('T-minus', n)
24-
n -= 1
25-
time.sleep(5)
26-
27-
# Create and launch a thread
28-
from threading import Thread
29-
t = Thread(target=countdown, args=(10,))
30-
t.start()
31-
32-
When you create a thread instance, it doesn’t start executing until you invoke its start()
33-
method (which invokes the target function with the arguments you supplied).
34-
Threads are executed in their own system-level thread (e.g., a POSIX thread or Windows
35-
threads) that is fully managed by the host operating system. Once started, threads run
36-
independently until the target function returns. You can query a thread instance to see
37-
if it’s still running:
38-
39-
if t.is_alive():
40-
print('Still running')
41-
else:
42-
print('Completed')
43-
44-
You can also request to join with a thread, which waits for it to terminate:
45-
46-
t.join()
47-
48-
The interpreter remains running until all threads terminate. For long-running threads
49-
or background tasks that run forever, you should consider making the thread daemonic.
50-
For example:
51-
52-
t = Thread(target=countdown, args=(10,), daemon=True)
53-
t.start()
54-
55-
Daemonic threads can’t be joined. However, they are destroyed automatically when the
56-
main thread terminates.
57-
Beyond the two operations shown, there aren’t many other things you can do with
58-
threads. For example, there are no operations to terminate a thread, signal a thread,
59-
adjust its scheduling, or perform any other high-level operations. If you want these
60-
features, you need to build them yourself.
61-
If you want to be able to terminate threads, the thread must be programmed to poll for
62-
exit at selected points. For example, you might put your thread in a class such as this:
63-
64-
class CountdownTask:
65-
def __init__(self):
66-
self._running = True
67-
68-
def terminate(self):
69-
self._running = False
70-
71-
def run(self, n):
72-
while self._running and n > 0:
73-
print('T-minus', n)
74-
n -= 1
75-
time.sleep(5)
76-
77-
c = CountdownTask()
78-
t = Thread(target=c.run, args=(10,))
79-
t.start()
80-
...
81-
c.terminate() # Signal termination
82-
t.join() # Wait for actual termination (if needed)
83-
84-
Polling for thread termination can be tricky to coordinate if threads perform blocking
85-
operations such as I/O. For example, a thread blocked indefinitely on an I/O operation
86-
may never return to check if it’s been killed. To correctly deal with this case, you’ll need
87-
to carefully program thread to utilize timeout loops. For example:
88-
89-
class IOTask:
90-
def terminate(self):
91-
self._running = False
92-
93-
def run(self, sock):
94-
# sock is a socket
95-
sock.settimeout(5) # Set timeout period
96-
while self._running:
97-
# Perform a blocking I/O operation w/ timeout
98-
try:
99-
data = sock.recv(8192)
100-
break
101-
except socket.timeout:
102-
continue
103-
# Continued processing
104-
...
105-
# Terminated
106-
return
107-
13+
``threading`` 库可以在单独的线程中执行任何的在 Python 中可以调用的对象。你可以创建一个 ``Thread`` 对象并将你要执行的对象以 target 参数的形式提供给该对象。
14+
下面是一个简单的例子:
15+
16+
.. code-block:: python
17+
18+
# Code to execute in an independent thread
19+
import time
20+
def countdown(n):
21+
while n > 0:
22+
print('T-minus', n)
23+
n -= 1
24+
time.sleep(5)
25+
26+
# Create and launch a thread
27+
from threading import Thread
28+
t = Thread(target=countdown, args=(10,))
29+
t.start()
30+
31+
当你创建好一个线程对象后,该对象并不会立即执行,除非你调用它的 ``start()`` 方法(当你调用 ``start()`` 方法时,它会调用你传递进来的函数,并把你传递进来的参数传递给该函数)。Python中的线程会在一个单独的系统级线程中执行(比如说一个 POSIX 线程或者一个 Windows 线程),这些线程将由操作系统来全权管理。线程一旦启动,将独立执行直到目标函数返回。你可以查询一个线程对象的状态,看它是否还在执行:
32+
33+
.. code-block:: python
34+
35+
if t.is_alive():
36+
print('Still running')
37+
else:
38+
print('Completed')
39+
40+
你也可以将一个线程加入到当前线程,并等待它终止:
41+
42+
.. code-block:: python
43+
44+
t.join()
45+
46+
Python解释器在所有线程都终止后才继续执行代码剩余的部分。对于需要长时间运行的线程或者需要一直运行的后台任务,你应当考虑使用后台线程。
47+
例如:
48+
49+
.. code-block:: python
50+
51+
t = Thread(target=countdown, args=(10,), daemon=True)
52+
t.start()
53+
54+
后台线程无法等待,不过,这些线程会在主线程终止时自动销毁。
55+
除了如上所示的两个操作,并没有太多可以对线程做的事情。你无法结束一个线程,无法给它发送信号,无法调整它的调度,也无法执行其他高级操作。如果需要这些特性,你需要自己添加。比如说,如果你需要终止线程,那么这个线程必须通过编程在某个特定点轮询来退出。你可以像下边这样把线程放入一个类中:
56+
57+
.. code-block:: python
58+
59+
class CountdownTask:
60+
def __init__(self):
61+
self._running = True
62+
63+
def terminate(self):
64+
self._running = False
65+
66+
def run(self, n):
67+
while self._running and n > 0:
68+
print('T-minus', n)
69+
n -= 1
70+
time.sleep(5)
71+
72+
c = CountdownTask()
73+
t = Thread(target=c.run, args=(10,))
74+
t.start()
75+
c.terminate() # Signal termination
76+
t.join() # Wait for actual termination (if needed)
77+
78+
如果线程执行一些像I/O这样的阻塞操作,那么通过轮询来终止线程将使得线程之间的协调变得非常棘手。比如,如果一个线程一直阻塞在一个I/O操作上,它就永远无法返回,也就无法检查自己是否已经被结束了。要正确处理这些问题,你需要利用超时循环来小心操作线程。
79+
例子如下:
80+
81+
.. code-block:: python
82+
83+
class IOTask:
84+
def terminate(self):
85+
self._running = False
86+
87+
def run(self, sock):
88+
# sock is a socket
89+
sock.settimeout(5) # Set timeout period
90+
while self._running:
91+
# Perform a blocking I/O operation w/ timeout
92+
try:
93+
data = sock.recv(8192)
94+
break
95+
except socket.timeout:
96+
continue
97+
# Continued processing
98+
...
99+
# Terminated
100+
return
108101
|
109102
110103
----------
111104
讨论
112105
----------
113-
Due to a global interpreter lock (GIL), Python threads are restricted to an execution
114-
model that only allows one thread to execute in the interpreter at any given time. For
115-
this reason, Python threads should generally not be used for computationally intensive
116-
tasks where you are trying to achieve parallelism on multiple CPUs. They are much
117-
better suited for I/O handling and handling concurrent execution in code that performs
118-
blocking operations (e.g., waiting for I/O, waiting for results from a database, etc.).
119-
Sometimes you will see threads defined via inheritance from the Thread class. For
120-
example:
121-
122-
from threading import Thread
123-
124-
class CountdownThread(Thread):
125-
def __init__(self, n):
126-
super().__init__()
127-
self.n = 0
128-
def run(self):
129-
while self.n > 0:
130-
131-
print('T-minus', self.n)
132-
self.n -= 1
133-
time.sleep(5)
134-
135-
c = CountdownThread(5)
136-
c.start()
137-
138-
Although this works, it introduces an extra dependency between the code and the
139-
threading library. That is, you can only use the resulting code in the context of threads,
140-
whereas the technique shown earlier involves writing code with no explicit dependency
141-
on threading. By freeing your code of such dependencies, it becomes usable in other
142-
contexts that may or may not involve threads. For instance, you might be able to execute
143-
your code in a separate process using the multiprocessing module using code like this:
144-
145-
import multiprocessing
146-
c = CountdownTask(5)
147-
p = multiprocessing.Process(target=c.run)
148-
p.start()
149-
...
150-
151-
Again, this only works if the CountdownTask class has been written in a manner that is
152-
neutral to the actual means of concurrency (threads, processes, etc.).
106+
由于全局解释锁(GIL)的原因,Python 的线程被限制到同一时刻只允许一个线程执行这样一个执行模型。所以,Python 的线程更适用于处理I/O和其他需要并发执行的阻塞操作(比如等待I/O、等待从数据库获取数据等等),而不是需要多处理器并行的计算密集型任务。
107+
108+
有时你会看到下边这种通过继承 ``Thread`` 类来实现的线程:
109+
110+
.. code-block:: python
111+
112+
from threading import Thread
113+
114+
class CountdownThread(Thread):
115+
def __init__(self, n):
116+
super().__init__()
117+
self.n = 0
118+
def run(self):
119+
while self.n > 0:
120+
121+
print('T-minus', self.n)
122+
self.n -= 1
123+
time.sleep(5)
124+
125+
c = CountdownThread(5)
126+
c.start()
127+
128+
尽管这样也可以工作,但这使得你的代码依赖于 ``threading`` 库,所以你的这些代码只能在线程上下文中使用。上文所写的那些代码、函数都是与 ``threading`` 库无关的,这样就使得这些代码可以被用在其他的上下文中,可能与线程有关,也可能与线程无关。比如,你可以通过 ``multiprocessing`` 模块在一个单独的进程中执行你的代码:
129+
130+
.. code-block:: python
131+
132+
import multiprocessing
133+
c = CountdownTask(5)
134+
p = multiprocessing.Process(target=c.run)
135+
p.start()
136+
137+
138+
再次重申,这段代码仅适用于 CountdownTask 类是以独立于实际的并发手段(多线程、多进程等等)实现的情况。

0 commit comments

Comments
 (0)