Bộ nhớ chia sẻ đa xử lý Python

là gói hỗ trợ các quy trình sinh sản bằng API tương tự như mô-đun. The package offers both local and remote concurrency, effectively side-stepping the by using subprocesses instead of threads. Due to this, the module allows the programmer to fully leverage multiple processors on a given machine. It runs on both Unix and Windows

The module also introduces APIs which do not have analogs in the module. A prime example of this is the object which offers a convenient means of parallelizing the execution of a function across multiple input values, distributing the input data across processes [data parallelism]. The following example demonstrates the common practice of defining such functions in a module so that child processes can successfully import that module. This basic example of data parallelism using ,

from multiprocessing import Pool

def f[x]:
    return x*x

if __name__ == '__main__':
    with Pool[5] as p:
        print[p.map[f, [1, 2, 3]]]

sẽ in ra đầu ra tiêu chuẩn

[1, 4, 9]

17. 2. 1. 1. The class

In , processes are spawned by creating a object and then calling its method. follows the API of . A trivial example of a multiprocess program is

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]

To show the individual process IDs involved, here is an expanded example

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]

For an explanation of why the

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
0 part is necessary, see

17. 2. 1. 2. Contexts and start methods

Tùy thuộc vào nền tảng, hỗ trợ ba cách để bắt đầu một quy trình. Các phương thức bắt đầu này là

đẻ trứng

Quá trình mẹ bắt đầu một quá trình phiên dịch python mới. Tiến trình con sẽ chỉ kế thừa những tài nguyên cần thiết để chạy phương thức đối tượng tiến trình. Cụ thể, các bộ mô tả và xử lý tệp không cần thiết từ quy trình gốc sẽ không được kế thừa. Bắt đầu một quy trình bằng phương pháp này khá chậm so với sử dụng fork hoặc forkserver

Có sẵn trên Unix và Windows. Mặc định trên Windows

cái nĩa

Quá trình mẹ sử dụng để rẽ nhánh trình thông dịch Python. Tiến trình con, khi nó bắt đầu, thực sự giống với tiến trình cha. Tất cả các tài nguyên của cha mẹ được kế thừa bởi tiến trình con. Lưu ý rằng việc rẽ nhánh một cách an toàn một quy trình đa luồng là một vấn đề

Chỉ khả dụng trên Unix. Mặc định trên Unix

máy chủ rẽ nhánh

Khi chương trình bắt đầu và chọn phương thức khởi động máy chủ rẽ nhánh, một quy trình máy chủ sẽ được bắt đầu. Từ đó trở đi, bất cứ khi nào cần một quy trình mới, quy trình mẹ sẽ kết nối với máy chủ và yêu cầu nó rẽ nhánh một quy trình mới. Quá trình máy chủ ngã ba là một luồng nên nó an toàn khi sử dụng. Không có tài nguyên không cần thiết được kế thừa

Available on Unix platforms which support passing file descriptors over Unix pipes

Changed in version 3. 4. spawn added on all unix platforms, and forkserver added for some unix platforms. Child processes no longer inherit all of the parents inheritable handles on Windows.

On Unix using the spawn or forkserver start methods will also start a semaphore tracker process which tracks the unlinked named semaphores created by processes of the program. When all processes have exited the semaphore tracker unlinks any remaining semaphores. Usually there should be none, but if a process was killed by a signal there may be some “leaked” semaphores. [Unlinking the named semaphores is a serious matter since the system allows only a limited number, and they will not be automatically unlinked until the next reboot. ]

To select a start method you use the in the

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
0 clause of the main module. For example

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]

không nên được sử dụng nhiều hơn một lần trong chương trình

Alternatively, you can use to obtain a context object. Context objects have the same API as the multiprocessing module, and allow one to use multiple start methods in the same program

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]

Note that objects related to one context may not be compatible with processes for a different context. In particular, locks created using the fork context cannot be passed to processes started using the spawn or forkserver start methods

A library which wants to use a particular start method should probably use to avoid interfering with the choice of the library user

17. 2. 1. 3. Exchanging objects between processes

supports two types of communication channel between processes

Queues

The class is a near clone of . For example

________số 8_______

Hàng đợi là luồng và xử lý an toàn

ống

Hàm trả về một cặp đối tượng kết nối được kết nối bằng một đường ống mà theo mặc định là song công [hai chiều]. Ví dụ

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]

Hai đối tượng kết nối được trả về bằng đại diện cho hai đầu của đường ống. Mỗi đối tượng kết nối có và các phương thức [trong số những đối tượng khác]. Lưu ý rằng dữ liệu trong một đường ống có thể bị hỏng nếu hai quy trình [hoặc luồng] cố gắng đọc hoặc ghi vào cùng một đầu của đường ống cùng một lúc. Tất nhiên, không có nguy cơ tham nhũng từ các quy trình sử dụng các đầu khác nhau của đường ống cùng một lúc

17. 2. 1. 4. Đồng bộ hóa giữa các quy trình

chứa tương đương của tất cả các nguyên thủy đồng bộ hóa từ. Chẳng hạn, người ta có thể sử dụng khóa để đảm bảo rằng mỗi lần chỉ có một quy trình in ra đầu ra tiêu chuẩn

from multiprocessing import Process, Lock

def f[l, i]:
    l.acquire[]
    try:
        print['hello world', i]
    finally:
        l.release[]

if __name__ == '__main__':
    lock = Lock[]

    for num in range[10]:
        Process[target=f, args=[lock, num]].start[]

Không sử dụng đầu ra khóa từ các quy trình khác nhau có thể bị lẫn lộn

17. 2. 1. 5. Chia sẻ trạng thái giữa các tiến trình

Như đã đề cập ở trên, khi thực hiện lập trình đồng thời, tốt nhất là tránh sử dụng trạng thái chia sẻ càng nhiều càng tốt. Điều này đặc biệt đúng khi sử dụng nhiều quy trình

Tuy nhiên, nếu bạn thực sự cần sử dụng một số dữ liệu được chia sẻ thì hãy cung cấp một số cách để thực hiện việc đó

Bộ nhớ dùng chung

Dữ liệu có thể được lưu trữ trong bản đồ bộ nhớ dùng chung bằng cách sử dụng hoặc. Ví dụ, đoạn mã sau

from multiprocessing import Process, Value, Array

def f[n, a]:
    n.value = 3.1415927
    for i in range[len[a]]:
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value['d', 0.0]
    arr = Array['i', range[10]]

    p = Process[target=f, args=[num, arr]]
    p.start[]
    p.join[]

    print[num.value]
    print[arr[:]]

sẽ in

[1, 4, 9]
0

Các đối số

from multiprocessing import Process, Value, Array

def f[n, a]:
    n.value = 3.1415927
    for i in range[len[a]]:
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value['d', 0.0]
    arr = Array['i', range[10]]

    p = Process[target=f, args=[num, arr]]
    p.start[]
    p.join[]

    print[num.value]
    print[arr[:]]
2 và
from multiprocessing import Process, Value, Array

def f[n, a]:
    n.value = 3.1415927
    for i in range[len[a]]:
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value['d', 0.0]
    arr = Array['i', range[10]]

    p = Process[target=f, args=[num, arr]]
    p.start[]
    p.join[]

    print[num.value]
    print[arr[:]]
3 được sử dụng khi tạo
from multiprocessing import Process, Value, Array

def f[n, a]:
    n.value = 3.1415927
    for i in range[len[a]]:
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value['d', 0.0]
    arr = Array['i', range[10]]

    p = Process[target=f, args=[num, arr]]
    p.start[]
    p.join[]

    print[num.value]
    print[arr[:]]
4 và
from multiprocessing import Process, Value, Array

def f[n, a]:
    n.value = 3.1415927
    for i in range[len[a]]:
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value['d', 0.0]
    arr = Array['i', range[10]]

    p = Process[target=f, args=[num, arr]]
    p.start[]
    p.join[]

    print[num.value]
    print[arr[:]]
5 là các loại mã kiểu được sử dụng bởi mô-đun.
from multiprocessing import Process, Value, Array

def f[n, a]:
    n.value = 3.1415927
    for i in range[len[a]]:
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value['d', 0.0]
    arr = Array['i', range[10]]

    p = Process[target=f, args=[num, arr]]
    p.start[]
    p.join[]

    print[num.value]
    print[arr[:]]
2 biểu thị số float có độ chính xác kép và
from multiprocessing import Process, Value, Array

def f[n, a]:
    n.value = 3.1415927
    for i in range[len[a]]:
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value['d', 0.0]
    arr = Array['i', range[10]]

    p = Process[target=f, args=[num, arr]]
    p.start[]
    p.join[]

    print[num.value]
    print[arr[:]]
3 biểu thị số nguyên có dấu. Các đối tượng được chia sẻ này sẽ được xử lý và an toàn cho luồng

Để linh hoạt hơn trong việc sử dụng bộ nhớ dùng chung, người ta có thể sử dụng mô-đun hỗ trợ tạo các đối tượng ctypes tùy ý được cấp phát từ bộ nhớ dùng chung

quy trình máy chủ

Một đối tượng người quản lý được trả về bởi

[1, 4, 9]
00 kiểm soát một quy trình máy chủ chứa các đối tượng Python và cho phép các quy trình khác thao tác chúng bằng proxy

Người quản lý được trả về bởi

[1, 4, 9]
00 sẽ hỗ trợ các loại , , , , , , , , , , , và. Ví dụ,

[1, 4, 9]
1

sẽ in

[1, 4, 9]
2

Trình quản lý quy trình máy chủ linh hoạt hơn so với việc sử dụng các đối tượng bộ nhớ dùng chung vì chúng có thể được tạo để hỗ trợ các loại đối tượng tùy ý. Ngoài ra, một trình quản lý duy nhất có thể được chia sẻ bởi các quy trình trên các máy tính khác nhau qua mạng. Tuy nhiên, chúng chậm hơn so với sử dụng bộ nhớ dùng chung

17. 2. 1. 6. Sử dụng một nhóm công nhân

Lớp đại diện cho một nhóm các quy trình công nhân. Nó có các phương thức cho phép các tác vụ được giảm tải cho các quy trình công nhân theo một số cách khác nhau

Ví dụ

[1, 4, 9]
3

Lưu ý rằng các phương thức của một nhóm chỉ nên được sử dụng bởi quy trình đã tạo ra nó

Ghi chú

Chức năng trong gói này yêu cầu trẻ em có thể nhập mô-đun

[1, 4, 9]
16. Điều này được đề cập trong tuy nhiên nó đáng được chỉ ra ở đây. Điều này có nghĩa là một số ví dụ, chẳng hạn như các ví dụ sẽ không hoạt động trong trình thông dịch tương tác. Ví dụ

[1, 4, 9]
4

[Nếu bạn thử điều này, nó sẽ thực sự tạo ra ba lần theo dõi đầy đủ xen kẽ theo kiểu bán ngẫu nhiên, và sau đó bạn có thể phải dừng quá trình chính bằng cách nào đó. ]

17. 2. 2. Thẩm quyền giải quyết

Gói chủ yếu sao chép API của mô-đun

17. 2. 2. 1. và ngoại lệ

lớp
[1, 4, 9]
21
[1, 4, 9]
22 [ group=None, target=None, name=None, args=[], kwargs={}, *, ]

Các đối tượng quy trình đại diện cho hoạt động được chạy trong một quy trình riêng biệt. Lớp có tương đương với tất cả các phương thức của

Hàm tạo phải luôn được gọi với các đối số từ khóa. nhóm phải luôn là

[1, 4, 9]
25; . target là đối tượng có thể gọi được gọi theo phương thức. Nó mặc định là
[1, 4, 9]
25, nghĩa là không có gì được gọi. name is the process name [see for more details]. args là bộ đối số cho lệnh gọi đích. kwargs là một từ điển các đối số từ khóa cho lệnh gọi đích. Nếu được cung cấp, đối số trình nền chỉ có từ khóa sẽ đặt cờ quy trình thành
[1, 4, 9]
31 hoặc
[1, 4, 9]
32. Nếu
[1, 4, 9]
25 [mặc định], cờ này sẽ được kế thừa từ quá trình tạo

Theo mặc định, không có đối số nào được chuyển đến đích

Nếu một lớp con ghi đè hàm tạo, nó phải đảm bảo rằng nó gọi hàm tạo của lớp cơ sở [

[1, 4, 9]
34] trước khi thực hiện bất kỳ điều gì khác đối với quy trình

Đã thay đổi trong phiên bản 3. 3. Đã thêm đối số daemon.

[1, 4, 9]
35 []

Phương thức biểu diễn hoạt động của tiến trình

Bạn có thể ghi đè phương thức này trong một lớp con. Phương thức tiêu chuẩn gọi đối tượng có thể gọi được truyền cho hàm tạo của đối tượng làm đối số đích, nếu có, với các đối số tuần tự và từ khóa được lấy từ các đối số args và kwargs tương ứng

[1, 4, 9]
37 []

Bắt đầu hoạt động của quy trình

Điều này phải được gọi nhiều nhất một lần cho mỗi đối tượng quy trình. Nó sắp xếp để phương thức của đối tượng được gọi trong một tiến trình riêng biệt

[1, 4, 9]
39 [[ hết giờ ]]

Nếu thời gian chờ của đối số tùy chọn là

[1, 4, 9]
25 [mặc định], phương thức sẽ chặn cho đến khi quá trình có phương thức được gọi kết thúc. Nếu thời gian chờ là một số dương, nó sẽ chặn tối đa các giây hết thời gian chờ. Lưu ý rằng phương thức trả về
[1, 4, 9]
25 nếu quá trình của nó kết thúc hoặc nếu phương thức hết thời gian chờ. Kiểm tra quy trình để xác định xem nó có chấm dứt không

Một quá trình có thể được tham gia nhiều lần

Một quá trình không thể tự tham gia vì điều này sẽ gây ra bế tắc. Có lỗi khi cố gắng tham gia một quy trình trước khi nó được bắt đầu

[1, 4, 9]
44

The process’s name. The name is a string used for identification purposes only. It has no semantics. Multiple processes may be given the same name

The initial name is set by the constructor. If no explicit name is provided to the constructor, a name of the form ‘Process-N1. N2. Nk‘ is constructed, where each Nk is the N-th child of its parent

[1, 4, 9]
45 []

Return whether the process is alive

Roughly, a process object is alive from the moment the method returns until the child process terminates

[1, 4, 9]
47

The process’s daemon flag, a Boolean value. This must be set before is called

The initial value is inherited from the creating process

When a process exits, it attempts to terminate all of its daemonic child processes

Note that a daemonic process is not allowed to create child processes. Otherwise a daemonic process would leave its children orphaned if it gets terminated when its parent process exits. Additionally, these are not Unix daemons or services, they are normal processes that will be terminated [and not joined] if non-daemonic processes have exited

In addition to the API, objects also support the following attributes and methods

[1, 4, 9]
51

Return the process ID. Before the process is spawned, this will be

[1, 4, 9]
25

[1, 4, 9]
53

The child’s exit code. This will be

[1, 4, 9]
25 if the process has not yet terminated. A negative value -N indicates that the child was terminated by signal N

[1, 4, 9]
55

Khóa xác thực của quy trình [một chuỗi byte]

Khi được khởi tạo, quy trình chính được gán một chuỗi ngẫu nhiên bằng cách sử dụng

Khi một đối tượng được tạo, nó sẽ kế thừa khóa xác thực của quy trình cha của nó, mặc dù điều này có thể được thay đổi bằng cách đặt thành một chuỗi byte khác

Thấy

[1, 4, 9]
60

Một điều khiển số của một đối tượng hệ thống sẽ trở thành "sẵn sàng" khi quá trình kết thúc

Bạn có thể sử dụng giá trị này nếu bạn muốn đợi nhiều sự kiện cùng một lúc bằng cách sử dụng. Nếu không thì việc gọi đơn giản hơn

Trên Windows, đây là một trình điều khiển hệ điều hành có thể sử dụng được với nhóm lệnh gọi API

[1, 4, 9]
63 và
[1, 4, 9]
64. Trên Unix, đây là một bộ mô tả tệp có thể sử dụng được với các nguyên hàm từ mô-đun

Mới trong phiên bản 3. 3

[1, 4, 9]
66 []

Chấm dứt quá trình. Trên Unix, điều này được thực hiện bằng cách sử dụng tín hiệu

[1, 4, 9]
67; . Lưu ý rằng các trình xử lý thoát và các mệnh đề cuối cùng, v.v. , sẽ không được thực hiện

Note that descendant processes of the process will not be terminated – they will simply become orphaned

Cảnh báo

Nếu phương pháp này được sử dụng khi quy trình được liên kết đang sử dụng đường ống hoặc hàng đợi thì đường ống hoặc hàng đợi đó có thể bị hỏng và có thể trở nên không sử dụng được bởi quy trình khác. Tương tự, nếu quá trình đã có khóa hoặc semaphore, v.v. sau đó chấm dứt nó có khả năng gây ra bế tắc cho các quá trình khác

[1, 4, 9]
69 []

Tương tự nhưng sử dụng tín hiệu

[1, 4, 9]
71 trên Unix

Mới trong phiên bản 3. 7

[1, 4, 9]
72 []

Đóng đối tượng, giải phóng tất cả các tài nguyên được liên kết với nó. được nâng lên nếu quá trình cơ bản vẫn đang chạy. Sau khi trả về thành công, hầu hết các phương thức và thuộc tính khác của đối tượng sẽ tăng

Mới trong phiên bản 3. 7

Lưu ý rằng các phương thức , , và chỉ nên được gọi bởi quy trình đã tạo đối tượng quy trình

Ví dụ sử dụng một số phương pháp của

[1, 4, 9]
5

ngoại lệ
[1, 4, 9]
21____1_______85

Lớp cơ sở của tất cả các ngoại lệ

ngoại lệ
[1, 4, 9]
21_______1_______88

Ngoại lệ được đưa ra khi đối tượng bộ đệm được cung cấp quá nhỏ để đọc thông báo

Nếu

[1, 4, 9]
90 là một thể hiện của thì
[1, 4, 9]
92 sẽ đưa ra thông báo dưới dạng chuỗi byte

ngoại lệ
[1, 4, 9]
21_______1_______94

Xảy ra khi có lỗi xác thực

ngoại lệ
[1, 4, 9]
21_______1_______96

Tăng theo các phương thức có thời gian chờ khi hết thời gian chờ

17. 2. 2. 2. Đường ống và hàng đợi

Khi sử dụng nhiều quy trình, người ta thường sử dụng tính năng truyền thông báo để liên lạc giữa các quy trình và tránh phải sử dụng bất kỳ nguyên tắc đồng bộ hóa nào như khóa

Để truyền tin nhắn, người ta có thể sử dụng [đối với kết nối giữa hai quy trình] hoặc hàng đợi [cho phép nhiều nhà sản xuất và người tiêu dùng]

Các và các loại là hàng đợi FIFO nhiều nhà sản xuất, nhiều người tiêu dùng được mô hình hóa trên lớp trong thư viện chuẩn. Chúng khác nhau ở chỗ thiếu các phương thức và được đưa vào Python 2. lớp 5

Nếu bạn sử dụng thì bạn phải gọi cho từng tác vụ đã bị xóa khỏi hàng đợi, nếu không, semaphore được sử dụng để đếm số lượng tác vụ chưa hoàn thành cuối cùng có thể bị tràn, tạo ra một ngoại lệ

Lưu ý rằng người ta cũng có thể tạo hàng đợi dùng chung bằng cách sử dụng đối tượng người quản lý – xem

Ghi chú

sử dụng thông thường và ngoại lệ để báo hiệu thời gian chờ. Chúng không có sẵn trong không gian tên nên bạn cần nhập chúng từ

Ghi chú

Khi một đối tượng được đưa vào hàng đợi, đối tượng sẽ được chọn và một chuỗi nền sau đó sẽ xóa dữ liệu đã chọn vào một đường ống bên dưới. Điều này có một số hậu quả hơi ngạc nhiên, nhưng sẽ không gây ra bất kỳ khó khăn thực tế nào – nếu chúng thực sự làm phiền bạn thì thay vào đó, bạn có thể sử dụng hàng đợi được tạo bằng

  1. Sau khi đặt một đối tượng vào một hàng đợi trống, có thể có một độ trễ vô cùng nhỏ trước khi phương thức của hàng đợi trả về và có thể trả về mà không tăng
  2. Nếu nhiều quá trình đang xếp hàng các đối tượng, có thể các đối tượng được nhận ở đầu kia không theo thứ tự. Tuy nhiên, các đối tượng được xử lý bởi cùng một quy trình sẽ luôn theo thứ tự mong đợi đối với nhau

Cảnh báo

Nếu một quá trình bị hủy khi sử dụng hoặc trong khi nó đang cố sử dụng a , thì dữ liệu trong hàng đợi có khả năng bị hỏng. Điều này có thể khiến bất kỳ quy trình nào khác gặp ngoại lệ khi nó cố sử dụng hàng đợi sau này

Cảnh báo

Như đã đề cập ở trên, nếu một tiến trình con đã đặt các mục vào hàng đợi [và nó chưa được sử dụng ], thì tiến trình đó sẽ không kết thúc cho đến khi tất cả các mục trong bộ đệm đã được xóa vào đường ống

Điều này có nghĩa là nếu bạn cố gắng tham gia quá trình đó, bạn có thể gặp bế tắc trừ khi bạn chắc chắn rằng tất cả các mục được đưa vào hàng đợi đã được sử dụng hết. Tương tự, nếu tiến trình con không phải là daemon thì tiến trình cha có thể bị treo khi thoát khi nó cố gắng nối tất cả các con không phải daemon của nó

Lưu ý rằng hàng đợi được tạo bằng trình quản lý không gặp sự cố này. Thấy

Để biết ví dụ về việc sử dụng hàng đợi để liên lạc giữa các quá trình, hãy xem

[1, 4, 9]
21
from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22 [[ song công ]]

Trả về một cặp

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23 đối tượng đại diện cho các đầu của một đường ống

Nếu song công là

[1, 4, 9]
31 [mặc định] thì đường ống là hai chiều. Nếu song công là
[1, 4, 9]
32 thì đường ống là một chiều.
from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
27 chỉ có thể được sử dụng để nhận tin nhắn và
from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
28 chỉ có thể được sử dụng để gửi tin nhắn

lớp
[1, 4, 9]
21
from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
30 [[ kích thước tối đa ]]

Trả về một hàng đợi chia sẻ quy trình được thực hiện bằng cách sử dụng một đường ống và một vài ổ khóa/semaphores. Khi một quy trình lần đầu tiên đặt một mục vào hàng đợi, một chuỗi trung chuyển được bắt đầu để chuyển các đối tượng từ bộ đệm vào đường ống

Thông thường và ngoại lệ từ mô-đun của thư viện tiêu chuẩn được nâng lên để báo hiệu thời gian chờ

thực hiện tất cả các phương pháp ngoại trừ và

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
38 []

Trả về kích thước gần đúng của hàng đợi. Do ngữ nghĩa đa luồng/đa xử lý, con số này không đáng tin cậy

Lưu ý rằng điều này có thể tăng lên trên các nền tảng Unix như Mac OS X nơi mà

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
40 không được triển khai

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
41 []

Trả lại

[1, 4, 9]
31 nếu hàng đợi trống, ngược lại là
[1, 4, 9]
32. Do ngữ nghĩa đa luồng/đa xử lý, điều này không đáng tin cậy

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
44 []

Trả lại

[1, 4, 9]
31 nếu hàng đợi đã đầy, ngược lại là
[1, 4, 9]
32. Do ngữ nghĩa đa luồng/đa xử lý, điều này không đáng tin cậy

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
47 [ obj [ , chặn [, timeout]]]

Đặt obj vào hàng đợi. Nếu khối đối số tùy chọn là

[1, 4, 9]
31 [mặc định] và thời gian chờ là
[1, 4, 9]
25 [mặc định], hãy chặn nếu cần cho đến khi có chỗ trống. Nếu thời gian chờ là một số dương, nó sẽ chặn hầu hết các giây hết thời gian chờ và tăng ngoại lệ nếu không có chỗ trống trong thời gian đó. Mặt khác [khối là
[1, 4, 9]
32], đặt một mục vào hàng đợi nếu có sẵn một vị trí miễn phí, nếu không thì đưa ra ngoại lệ [thời gian chờ bị bỏ qua trong trường hợp đó]

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
53 [ obj ]

Tương đương với

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
54

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
55 [[ chặn [, timeout]]]

Xóa và trả lại một mục khỏi hàng đợi. Nếu khối đối số tùy chọn là

[1, 4, 9]
31 [mặc định] và thời gian chờ là
[1, 4, 9]
25 [mặc định], hãy chặn nếu cần thiết cho đến khi có sẵn một mục. Nếu thời gian chờ là một số dương, nó sẽ chặn tối đa các giây hết thời gian chờ và tăng ngoại lệ nếu không có mục nào có sẵn trong thời gian đó. Nếu không [khối là
[1, 4, 9]
32], hãy trả lại một mục nếu một mục có sẵn ngay lập tức, nếu không thì đưa ra ngoại lệ [thời gian chờ bị bỏ qua trong trường hợp đó]

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
61 []

Tương đương với

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
62

có một vài phương pháp bổ sung không tìm thấy trong. Các phương thức này thường không cần thiết đối với hầu hết mã

[1, 4, 9]
72 []

Cho biết rằng quy trình hiện tại sẽ không đưa thêm dữ liệu vào hàng đợi này. Chủ đề nền sẽ thoát sau khi nó đã xóa tất cả dữ liệu được lưu vào bộ đệm vào đường ống. Điều này được gọi tự động khi hàng đợi được thu gom rác

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
66 []

Tham gia chủ đề nền. Điều này chỉ có thể được sử dụng sau khi đã được gọi. Nó chặn cho đến khi luồng nền thoát ra, đảm bảo rằng tất cả dữ liệu trong bộ đệm đã được chuyển sang đường ống

Theo mặc định, nếu một quy trình không phải là người tạo hàng đợi thì khi thoát, nó sẽ cố gắng tham gia luồng nền của hàng đợi. Quá trình có thể gọi để thực hiện không làm gì cả

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
70 []

Ngăn chặn chặn. Đặc biệt, điều này ngăn luồng nền tự động được nối khi quá trình thoát – xem

Tên tốt hơn cho phương pháp này có thể là

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
73. Nó có khả năng làm mất dữ liệu trong hàng đợi và bạn gần như chắc chắn sẽ không cần sử dụng nó. Nó thực sự chỉ ở đó nếu bạn cần quy trình hiện tại thoát ngay lập tức mà không cần chờ chuyển dữ liệu đã xử lý sang đường ống bên dưới và bạn không quan tâm đến dữ liệu bị mất

Ghi chú

Chức năng của lớp này yêu cầu triển khai semaphore được chia sẻ chức năng trên hệ điều hành máy chủ. Nếu không có, chức năng trong lớp này sẽ bị vô hiệu hóa và cố gắng khởi tạo một sẽ dẫn đến một. Xem bpo-3770 để biết thêm thông tin. Điều này cũng đúng với bất kỳ loại hàng đợi chuyên biệt nào được liệt kê bên dưới

lớp
[1, 4, 9]
21_______2_______77

Nó là một loại đơn giản hóa, rất gần với một khóa

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
41 []

Trả lại

[1, 4, 9]
31 nếu hàng đợi trống, ngược lại là
[1, 4, 9]
32

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
55 []

Xóa và trả lại một mục khỏi hàng đợi

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
47 [ mục ]

Đặt mục vào hàng đợi

lớp
[1, 4, 9]
21
from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
86 [[ kích thước tối đa ]]

, một lớp con, là một hàng đợi có thêm và các phương thức

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
91 []

Chỉ ra rằng một nhiệm vụ được xử lý trước đây đã hoàn thành. Được sử dụng bởi người tiêu dùng xếp hàng. Đối với mỗi lần được sử dụng để tìm nạp một tác vụ, một lệnh gọi tiếp theo sẽ thông báo cho hàng đợi rằng quá trình xử lý tác vụ đã hoàn tất

Nếu một hiện đang bị chặn, nó sẽ tiếp tục khi tất cả các mục đã được xử lý [có nghĩa là đã nhận được lệnh gọi cho mọi mục đã được đưa vào hàng đợi]

Tăng nếu được gọi nhiều lần hơn số mục được đặt trong hàng đợi

[1, 4, 9]
39 []

Chặn cho đến khi tất cả các mục trong hàng đợi đã được nhận và xử lý

Số lượng nhiệm vụ chưa hoàn thành tăng lên bất cứ khi nào một mục được thêm vào hàng đợi. Số lượng giảm xuống bất cứ khi nào người tiêu dùng gọi để cho biết rằng mặt hàng đã được lấy và mọi công việc trên mặt hàng đó đã hoàn tất. Khi số lượng nhiệm vụ chưa hoàn thành giảm xuống 0, hãy bỏ chặn

17. 2. 2. 3. Điều khoản khác

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
02 []

Trả về danh sách tất cả các phần tử con còn sống của tiến trình hiện tại

Gọi điều này có tác dụng phụ là “tham gia” bất kỳ quy trình nào đã kết thúc

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
04 []

Trả về số lượng CPU trong hệ thống

Con số này không tương đương với số lượng CPU mà tiến trình hiện tại có thể sử dụng. Số lượng CPU có thể sử dụng có thể được lấy bằng

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
05

có thể tăng

Xem thêm

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
09 []

Trả về đối tượng tương ứng với quy trình hiện tại

Một chất tương tự của

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
13 []

Thêm hỗ trợ khi chương trình sử dụng đã bị đóng băng để tạo tệp thực thi Windows. [Đã được thử nghiệm với py2exe, PyInstaller và cx_Freeze. ]

Người ta cần gọi hàm này ngay sau dòng

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
0 của mô-đun chính. Ví dụ

[1, 4, 9]
6

Nếu dòng

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
16 bị bỏ qua thì việc cố gắng chạy tệp thực thi bị đóng băng sẽ tăng

Gọi

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
16 không có hiệu lực khi được gọi trên bất kỳ hệ điều hành nào ngoài Windows. Ngoài ra, nếu mô-đun đang được trình thông dịch Python trên Windows chạy bình thường [chương trình chưa bị đóng băng] thì
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
16 không có hiệu lực

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
21 []

Trả về danh sách các phương thức bắt đầu được hỗ trợ, phương thức đầu tiên là mặc định. The possible start methods are

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22,
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23 and
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
24. Trên Windows chỉ có
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23. Trên Unix,
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22 và
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23 luôn được hỗ trợ, với
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22 là mặc định

Mới trong phiên bản 3. 4

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
30 [ method=None ]

Trả về một đối tượng ngữ cảnh có cùng thuộc tính với mô-đun

Nếu phương thức là

[1, 4, 9]
25 thì ngữ cảnh mặc định được trả về. Nếu không thì phương thức phải là
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22,
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23,
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
24. được nâng lên nếu phương thức bắt đầu được chỉ định không khả dụng

Mới trong phiên bản 3. 4

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
38 [ allow_none=False ]

Trả về tên của phương thức bắt đầu được sử dụng để bắt đầu các quy trình

Nếu phương thức bắt đầu chưa được sửa và allow_none là sai, thì phương thức bắt đầu được sửa thành mặc định và tên được trả về. Nếu phương thức start chưa được sửa và allow_none là true thì trả về

[1, 4, 9]
25

Giá trị trả về có thể là

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22,
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23,
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
24 hoặc
[1, 4, 9]
25.
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22 là mặc định trên Unix, trong khi
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23 là mặc định trên Windows

Mới trong phiên bản 3. 4

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
47 []

Đặt đường dẫn của trình thông dịch Python để sử dụng khi bắt đầu một tiến trình con. [Theo mặc định được sử dụng]. Embedders có thể sẽ cần phải làm một cái gì đó như

[1, 4, 9]
7

trước khi họ có thể tạo các tiến trình con

Đã thay đổi trong phiên bản 3. 4. Hiện được hỗ trợ trên Unix khi sử dụng phương thức khởi động

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23.

[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
51 [ phương pháp ]

Đặt phương thức sẽ được sử dụng để bắt đầu các tiến trình con. phương pháp có thể là

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
22,
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
23 hoặc
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
24

Lưu ý rằng điều này nên được gọi nhiều nhất một lần và nó phải được bảo vệ bên trong mệnh đề

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
0 của mô-đun chính

Mới trong phiên bản 3. 4

Ghi chú

không chứa tương tự của , , , , hoặc

17. 2. 2. 4. Đối tượng kết nối

Các đối tượng kết nối cho phép gửi và nhận các đối tượng hoặc chuỗi có thể chọn. Chúng có thể được coi là ổ cắm được kết nối theo định hướng thông báo

Các đối tượng kết nối thường được tạo bằng cách sử dụng – xem thêm

lớp
[1, 4, 9]
21
from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
65_______3_______66 [ obj ]

Gửi một đối tượng đến đầu kia của kết nối sẽ được đọc bằng cách sử dụng

Đối tượng phải được picklable. Dưa chua rất lớn [khoảng 32 MiB+, mặc dù nó phụ thuộc vào hệ điều hành] có thể gây ra ngoại lệ

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
69 []

Trả lại một đối tượng được gửi từ đầu kia của kết nối bằng cách sử dụng. Chặn cho đến khi có thứ gì đó để nhận. Tăng nếu không còn gì để nhận và đầu kia đã đóng

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
72 []

Trả lại bộ mô tả tệp hoặc tay cầm được sử dụng bởi kết nối

[1, 4, 9]
72 []

Đóng kết nối

Điều này được gọi tự động khi kết nối được thu gom rác

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
74 [[ hết giờ ]]

Trả về xem có bất kỳ dữ liệu nào có sẵn để đọc không

Nếu thời gian chờ không được chỉ định thì nó sẽ quay lại ngay lập tức. Nếu thời gian chờ là một số thì số này chỉ định thời gian tối đa tính bằng giây để chặn. Nếu thời gian chờ là

[1, 4, 9]
25 thì thời gian chờ vô hạn được sử dụng

Lưu ý rằng nhiều đối tượng kết nối có thể được thăm dò cùng một lúc bằng cách sử dụng

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
77 [ bộ đệm [ , phần bù [, size]]]

Gửi dữ liệu byte từ a dưới dạng một tin nhắn hoàn chỉnh

Nếu offset được đưa ra thì dữ liệu được đọc từ vị trí đó trong bộ đệm. Nếu kích thước được đưa ra thì nhiều byte sẽ được đọc từ bộ đệm. Bộ đệm rất lớn [khoảng 32 MiB+, mặc dù nó phụ thuộc vào HĐH] có thể gây ra ngoại lệ

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
79 [[ độ dài tối đa ]]

Trả về một thông báo đầy đủ về dữ liệu byte được gửi từ đầu kia của kết nối dưới dạng chuỗi. Chặn cho đến khi có thứ gì đó để nhận. Tăng nếu không còn gì để nhận và đầu kia đã đóng

Nếu độ dài tối đa được chỉ định và thông báo dài hơn độ dài tối đa thì sẽ được nâng lên và kết nối sẽ không thể đọc được nữa

Đã thay đổi trong phiên bản 3. 3. Hàm này được sử dụng để tăng , hiện là bí danh của.

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
84 [ bộ đệm [ , phần bù ]]

Đọc vào bộ đệm một thông báo đầy đủ về dữ liệu byte được gửi từ đầu kia của kết nối và trả về số byte trong thông báo. Chặn cho đến khi có thứ gì đó để nhận. Tăng nếu không còn gì để nhận và đầu kia đã đóng

bộ đệm phải là một bộ đệm có thể ghi. Nếu offset được đưa ra thì thông báo sẽ được ghi vào bộ đệm từ vị trí đó. Độ lệch phải là một số nguyên không âm nhỏ hơn độ dài của bộ đệm [tính bằng byte]

Nếu bộ đệm quá ngắn thì một ngoại lệ sẽ được đưa ra và thông báo hoàn chỉnh có sẵn dưới dạng

[1, 4, 9]
92 trong đó
[1, 4, 9]
90 là trường hợp ngoại lệ

Đã thay đổi trong phiên bản 3. 3. Bản thân các đối tượng kết nối giờ đây có thể được chuyển giữa các quy trình bằng cách sử dụng và.

Mới trong phiên bản 3. 3. Các đối tượng kết nối hiện hỗ trợ giao thức quản lý ngữ cảnh – xem. trả về đối tượng kết nối và gọi.

Ví dụ

[1, 4, 9]
8

Cảnh báo

Phương pháp này tự động giải mã dữ liệu mà nó nhận được, đây có thể là rủi ro bảo mật trừ khi bạn có thể tin tưởng vào quy trình đã gửi tin nhắn

Do đó, trừ khi đối tượng kết nối được tạo bằng cách sử dụng, bạn chỉ nên sử dụng các phương thức và sau khi thực hiện một số loại xác thực. Thấy

Cảnh báo

Nếu một quá trình bị giết trong khi nó đang cố đọc hoặc ghi vào một đường dẫn thì dữ liệu trong đường dẫn đó có khả năng bị hỏng, vì có thể không thể chắc chắn ranh giới của thông báo nằm ở đâu

17. 2. 2. 5. nguyên thủy đồng bộ hóa

Nói chung, các nguyên hàm đồng bộ hóa không cần thiết trong chương trình đa xử lý như trong chương trình đa luồng. Xem tài liệu cho mô-đun

Lưu ý rằng người ta cũng có thể tạo các nguyên hàm đồng bộ hóa bằng cách sử dụng đối tượng trình quản lý - xem

lớp
[1, 4, 9]
21____6_______00 [ các bên [ , hành động [, timeout]]]

Đối tượng rào cản. một bản sao của

Mới trong phiên bản 3. 3

lớp
[1, 4, 9]
21
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03 [[ giá trị ]]

Một đối tượng semaphore giới hạn. một tương tự gần gũi của

Một sự khác biệt duy nhất từ ​​tương tự gần của nó tồn tại. đối số đầu tiên của phương thức

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
05 của nó được đặt tên là khối, phù hợp với

Ghi chú

Trên Mac OS X, điều này không thể phân biệt được vì

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
40 không được triển khai trên nền tảng đó

lớp
[1, 4, 9]
21
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
10 [[ khóa ]]

Biến điều kiện. một bí danh cho

Nếu lock được chỉ định thì nó phải là một hoặc đối tượng từ

Đã thay đổi trong phiên bản 3. 3. Phương thức đã được thêm vào.

lớp
[1, 4, 9]
21_______6_______17

một bản sao của

lớp
[1, 4, 9]
21_______6_______20

Một đối tượng khóa không đệ quy. một tương tự gần gũi của. Khi một quy trình hoặc luồng đã nhận được khóa, các nỗ lực tiếp theo để lấy khóa đó từ bất kỳ quy trình hoặc luồng nào sẽ bị chặn cho đến khi khóa được giải phóng; . Các khái niệm và hành vi khi nó áp dụng cho các luồng được sao chép ở đây giống như khi nó áp dụng cho các quy trình hoặc luồng, ngoại trừ như đã lưu ý

Lưu ý rằng đó thực sự là một chức năng xuất xưởng trả về một thể hiện của

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
25 được khởi tạo với ngữ cảnh mặc định

hỗ trợ giao thức và do đó có thể được sử dụng trong các câu lệnh

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
28 [ block=True, timeout=None ]

Nhận khóa, chặn hoặc không chặn

Với đối số khối được đặt thành

[1, 4, 9]
31 [mặc định], lệnh gọi phương thức sẽ chặn cho đến khi khóa ở trạng thái mở khóa, sau đó đặt thành bị khóa và trả về
[1, 4, 9]
31. Lưu ý rằng tên của đối số đầu tiên này khác với tên trong

Với đối số khối được đặt thành

[1, 4, 9]
32, lệnh gọi phương thức không chặn. Nếu khóa hiện đang ở trạng thái khóa, hãy trả lại
[1, 4, 9]
32;

Khi được gọi với giá trị dương, dấu phẩy động cho thời gian chờ, hãy chặn tối đa số giây được chỉ định theo thời gian chờ miễn là không thể lấy được khóa. Các yêu cầu có giá trị âm cho thời gian chờ tương đương với thời gian chờ bằng 0. Các yêu cầu có giá trị thời gian chờ là

[1, 4, 9]
25 [mặc định] đặt khoảng thời gian chờ thành vô hạn. Lưu ý rằng việc xử lý các giá trị âm hoặc
[1, 4, 9]
25 cho thời gian chờ khác với hành vi được triển khai trong. Đối số thời gian chờ không có ý nghĩa thực tế nếu đối số khối được đặt thành
[1, 4, 9]
32 và do đó bị bỏ qua. Trả về
[1, 4, 9]
31 nếu đã lấy được khóa hoặc
[1, 4, 9]
32 nếu hết thời gian chờ

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
41 []

Phát hành một khóa. Điều này có thể được gọi từ bất kỳ quy trình hoặc luồng nào, không chỉ quy trình hoặc luồng ban đầu có khóa

Hành vi giống như ngoại trừ khi được gọi trên khóa đã mở khóa, a được nâng lên

lớp
[1, 4, 9]
21_______6_______45

Một đối tượng khóa đệ quy. một tương tự gần gũi của. Khóa đệ quy phải được giải phóng bởi quy trình hoặc luồng đã nhận được nó. Khi một quy trình hoặc luồng đã nhận được khóa đệ quy, cùng một quy trình hoặc luồng đó có thể lấy lại nó mà không bị chặn;

Lưu ý rằng đó thực sự là một chức năng xuất xưởng trả về một thể hiện của

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
48 được khởi tạo với ngữ cảnh mặc định

hỗ trợ giao thức và do đó có thể được sử dụng trong các câu lệnh

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
28 [ block=True, timeout=None ]

Nhận khóa, chặn hoặc không chặn

Khi được gọi với đối số khối được đặt thành

[1, 4, 9]
31, hãy chặn cho đến khi khóa ở trạng thái không khóa [không thuộc sở hữu của bất kỳ quy trình hoặc luồng nào] trừ khi khóa đã được sở hữu bởi quy trình hoặc luồng hiện tại. Sau đó, quy trình hoặc luồng hiện tại có quyền sở hữu khóa [nếu nó chưa có quyền sở hữu] và mức đệ quy bên trong khóa tăng thêm một, dẫn đến giá trị trả về là
[1, 4, 9]
31. Lưu ý rằng có một số khác biệt trong hành vi của đối số đầu tiên này so với việc triển khai , bắt đầu từ tên của chính đối số đó

Khi được gọi với đối số chặn được đặt thành

[1, 4, 9]
32, không chặn. If the lock has already been acquired [and thus is owned] by another process or thread, the current process or thread does not take ownership and the recursion level within the lock is not changed, resulting in a return value of
[1, 4, 9]
32. Nếu khóa ở trạng thái không khóa, quy trình hoặc luồng hiện tại sẽ có quyền sở hữu và mức đệ quy được tăng lên, dẫn đến giá trị trả về là
[1, 4, 9]
31

Việc sử dụng và hành vi của đối số hết thời gian chờ giống như trong. Lưu ý rằng một số hành vi hết thời gian chờ này khác với các hành vi được triển khai trong

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
41 []

Phát hành khóa, giảm mức đệ quy. Nếu sau khi giảm, mức đệ quy bằng 0, hãy đặt lại khóa thành mở khóa [không thuộc sở hữu của bất kỳ quy trình hoặc luồng nào] và nếu bất kỳ quy trình hoặc luồng nào khác bị chặn chờ khóa được mở khóa, hãy cho phép chính xác một trong số chúng tiếp tục. Nếu sau khi giảm, mức đệ quy vẫn khác không, thì khóa vẫn bị khóa và thuộc sở hữu của quy trình gọi hoặc luồng

Chỉ gọi phương thức này khi quá trình gọi hoặc luồng sở hữu khóa. An được nâng lên nếu phương thức này được gọi bởi một quy trình hoặc luồng không phải là chủ sở hữu hoặc nếu khóa ở trạng thái đã mở khóa [không có chủ sở hữu]. Lưu ý rằng loại ngoại lệ được đưa ra trong tình huống này khác với hành vi được triển khai trong

lớp
[1, 4, 9]
21
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
64 [[ giá trị ]]

Một đối tượng semaphore. một tương tự gần gũi của

Một sự khác biệt duy nhất từ ​​tương tự gần của nó tồn tại. đối số đầu tiên của phương thức

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
05 của nó được đặt tên là khối, phù hợp với

Ghi chú

Trên Mac OS X,

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
68 không được hỗ trợ, vì vậy, việc gọi
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
69 khi hết thời gian chờ sẽ mô phỏng hành vi của chức năng đó bằng cách sử dụng vòng lặp ngủ

Ghi chú

Nếu tín hiệu SIGINT được tạo bởi

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
70 đến trong khi luồng chính bị chặn bởi một cuộc gọi tới
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
71, , ,
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
74,
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
75 hoặc
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
76 thì cuộc gọi sẽ bị gián đoạn ngay lập tức và sẽ được nâng lên

Điều này khác với hành vi trong đó SIGINT sẽ bị bỏ qua trong khi các cuộc gọi chặn tương đương đang diễn ra

Ghi chú

Một số chức năng của gói này yêu cầu triển khai semaphore được chia sẻ chức năng trên hệ điều hành máy chủ. Nếu không có, mô-đun

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
79 sẽ bị vô hiệu hóa và cố gắng nhập nó sẽ dẫn đến lỗi. Xem bpo-3770 để biết thêm thông tin

17. 2. 2. 6. Đối tượng được chia sẻ

Có thể tạo các đối tượng dùng chung bằng bộ nhớ dùng chung có thể được kế thừa bởi các tiến trình con

[1, 4, 9]
21
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
83 [ typecode_or_type, *args, lock=True ]

Trả về một đối tượng được phân bổ từ bộ nhớ dùng chung. Theo mặc định, giá trị trả về thực sự là một trình bao bọc được đồng bộ hóa cho đối tượng. Bản thân đối tượng có thể được truy cập thông qua thuộc tính giá trị của một

typecode_or_type xác định loại đối tượng được trả về. nó là kiểu ctypes hoặc kiểu mã một ký tự thuộc loại được sử dụng bởi mô-đun. *args được chuyển đến hàm tạo cho loại

Nếu khóa là

[1, 4, 9]
31 [mặc định] thì một đối tượng khóa đệ quy mới được tạo để đồng bộ hóa quyền truy cập vào giá trị. Nếu lock là một đối tượng hoặc thì nó sẽ được sử dụng để đồng bộ hóa quyền truy cập vào giá trị. Nếu khóa là
[1, 4, 9]
32 thì quyền truy cập vào đối tượng được trả lại sẽ không được khóa tự động bảo vệ, do đó, nó sẽ không nhất thiết là "quy trình an toàn"

Các hoạt động như

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
91 liên quan đến đọc và viết không phải là nguyên tử. Vì vậy, nếu, ví dụ, bạn muốn tăng nguyên tử một giá trị được chia sẻ thì không đủ để làm

[1, 4, 9]
9

Giả sử khóa được liên kết là đệ quy [theo mặc định], thay vào đó, bạn có thể làm

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
0

Lưu ý rằng khóa là đối số chỉ có từ khóa

[1, 4, 9]
21
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
93 [ typecode_or_type, size_or_initializer, *, lock=True ]

Trả về một mảng ctypes được phân bổ từ bộ nhớ dùng chung. Theo mặc định, giá trị trả về thực sự là một trình bao bọc được đồng bộ hóa cho mảng

typecode_or_type xác định loại phần tử của mảng được trả về. nó là kiểu ctypes hoặc kiểu mã một ký tự thuộc loại được sử dụng bởi mô-đun. Nếu size_or_initializer là một số nguyên, thì nó xác định độ dài của mảng và ban đầu mảng sẽ bằng 0. Mặt khác, size_or_initializer là một chuỗi được sử dụng để khởi tạo mảng và độ dài của nó xác định độ dài của mảng

Nếu khóa là

[1, 4, 9]
31 [mặc định] thì một đối tượng khóa mới được tạo để đồng bộ hóa quyền truy cập vào giá trị. Nếu lock là một đối tượng hoặc thì nó sẽ được sử dụng để đồng bộ hóa quyền truy cập vào giá trị. Nếu khóa là
[1, 4, 9]
32 thì quyền truy cập vào đối tượng được trả lại sẽ không được khóa tự động bảo vệ, do đó, nó sẽ không nhất thiết là "quy trình an toàn"

Lưu ý rằng khóa chỉ là một đối số từ khóa

Lưu ý rằng một mảng có thuộc tính giá trị và thô cho phép một người sử dụng nó để lưu trữ và truy xuất chuỗi

17. 2. 2. 6. 1. mô-đun

Mô-đun này cung cấp các chức năng cấp phát đối tượng từ bộ nhớ dùng chung có thể được kế thừa bởi các tiến trình con

Ghi chú

Mặc dù có thể lưu trữ một con trỏ trong bộ nhớ dùng chung, hãy nhớ rằng con trỏ này sẽ đề cập đến một vị trí trong không gian địa chỉ của một quy trình cụ thể. Tuy nhiên, con trỏ rất có thể không hợp lệ trong ngữ cảnh của quy trình thứ hai và việc cố gắng hủy đăng ký con trỏ khỏi quy trình thứ hai có thể gây ra sự cố

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
04 [ typecode_or_type, size_or_initializer ]

Trả về một mảng ctypes được phân bổ từ bộ nhớ dùng chung

typecode_or_type xác định loại phần tử của mảng được trả về. nó là kiểu ctypes hoặc kiểu mã một ký tự thuộc loại được sử dụng bởi mô-đun. Nếu size_or_initializer là một số nguyên thì nó xác định độ dài của mảng và ban đầu mảng sẽ bằng 0. Mặt khác, size_or_initializer là một chuỗi được sử dụng để khởi tạo mảng và độ dài của nó xác định độ dài của mảng

Lưu ý rằng cài đặt và nhận một phần tử có khả năng không phải là nguyên tử – thay vào đó, hãy sử dụng để đảm bảo rằng quyền truy cập được tự động đồng bộ hóa bằng cách sử dụng khóa

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
08 [ typecode_or_type, *args ]

Trả về một đối tượng ctypes được phân bổ từ bộ nhớ dùng chung

typecode_or_type xác định loại đối tượng được trả về. nó là kiểu ctypes hoặc kiểu mã một ký tự thuộc loại được sử dụng bởi mô-đun. *args được chuyển đến hàm tạo cho loại

Lưu ý rằng cài đặt và nhận giá trị có khả năng không phải là nguyên tử – thay vào đó, hãy sử dụng để đảm bảo rằng quyền truy cập được tự động đồng bộ hóa bằng cách sử dụng khóa

Lưu ý rằng một mảng có các thuộc tính

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
12 và
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
13 cho phép một người sử dụng nó để lưu trữ và truy xuất các chuỗi – xem tài liệu về

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
93 [ typecode_or_type, size_or_initializer, *, lock=True ]

Giống như ngoại trừ tùy thuộc vào giá trị của khóa, trình bao bọc đồng bộ hóa an toàn cho quy trình có thể được trả về thay vì một mảng ctypes thô

Nếu khóa là

[1, 4, 9]
31 [mặc định] thì một đối tượng khóa mới được tạo để đồng bộ hóa quyền truy cập vào giá trị. Nếu lock là một đối tượng hoặc thì nó sẽ được sử dụng để đồng bộ hóa quyền truy cập vào giá trị. Nếu khóa là
[1, 4, 9]
32 thì quyền truy cập vào đối tượng được trả lại sẽ không được khóa tự động bảo vệ, do đó, nó sẽ không nhất thiết là "quy trình an toàn"

Lưu ý rằng khóa là đối số chỉ có từ khóa

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
83 [ typecode_or_type, *args, lock=True ]

Giống như ngoại trừ tùy thuộc vào giá trị của khóa, trình bao bọc đồng bộ hóa an toàn cho quy trình có thể được trả về thay vì đối tượng ctypes thô

Nếu khóa là

[1, 4, 9]
31 [mặc định] thì một đối tượng khóa mới được tạo để đồng bộ hóa quyền truy cập vào giá trị. Nếu lock là một đối tượng hoặc thì nó sẽ được sử dụng để đồng bộ hóa quyền truy cập vào giá trị. Nếu khóa là
[1, 4, 9]
32 thì quyền truy cập vào đối tượng được trả lại sẽ không được khóa tự động bảo vệ, do đó, nó sẽ không nhất thiết là "quy trình an toàn"

Lưu ý rằng khóa là đối số chỉ có từ khóa

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
30 [ obj ]

Trả về đối tượng ctypes được cấp phát từ bộ nhớ dùng chung, đây là bản sao của đối tượng ctypes obj

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
32 [ obj [ , khóa ]]

Return a process-safe wrapper object for a ctypes object which uses lock to synchronize access. Nếu khóa là

[1, 4, 9]
25 [mặc định] thì đối tượng được tạo tự động

Một trình bao bọc được đồng bộ hóa sẽ có hai phương thức ngoài các phương thức của đối tượng mà nó bao bọc.

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
35 trả về đối tượng được bọc và
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
36 trả về đối tượng khóa được sử dụng để đồng bộ hóa

Lưu ý rằng việc truy cập đối tượng ctypes thông qua trình bao bọc có thể chậm hơn rất nhiều so với truy cập đối tượng ctypes thô

Đã thay đổi trong phiên bản 3. 5. Các đối tượng được đồng bộ hóa hỗ trợ giao thức.

Bảng bên dưới so sánh cú pháp tạo các đối tượng ctypes dùng chung từ bộ nhớ dùng chung với cú pháp ctypes bình thường. [Trong bảng

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
37 là một phân lớp nào đó của. ]

ctypessharedctypes sử dụng typesharedctypes sử dụng typecodec_double[2. 4]Giá trị thô[c_double, 2. 4]Giá trị thô['d', 2. 4]MyStruct[4, 6]RawValue[MyStruct, 4, 6] [c_short * 7][]RawArray[c_short, 7]RawArray['h', 7][c_int * 3][9, 2, 8]RawArray

Dưới đây là một ví dụ trong đó một số đối tượng ctypes được sửa đổi bởi một tiến trình con

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
1

Kết quả in ra là

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
2

17. 2. 2. 7. quản lý

Trình quản lý cung cấp cách tạo dữ liệu có thể được chia sẻ giữa các quy trình khác nhau, bao gồm chia sẻ qua mạng giữa các quy trình chạy trên các máy khác nhau. Một đối tượng người quản lý điều khiển một quy trình máy chủ quản lý các đối tượng được chia sẻ. Các quy trình khác có thể truy cập các đối tượng được chia sẻ bằng cách sử dụng proxy

[1, 4, 9]
21
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
40 []

Trả về một đối tượng đã bắt đầu có thể được sử dụng để chia sẻ các đối tượng giữa các quy trình. Đối tượng trình quản lý được trả về tương ứng với một quy trình con được sinh ra và có các phương thức sẽ tạo các đối tượng được chia sẻ và trả về các proxy tương ứng

Các quy trình quản lý sẽ bị tắt ngay khi chúng được thu gom rác hoặc quy trình mẹ của chúng thoát ra. Các lớp quản lý được định nghĩa trong mô-đun

lớp
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
43
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
44 [[ địa chỉ [, authkey]]]

Tạo đối tượng BaseManager

Sau khi tạo, người ta nên gọi hoặc

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
46 để đảm bảo rằng đối tượng người quản lý đề cập đến quy trình người quản lý đã bắt đầu

address là địa chỉ mà quá trình quản lý lắng nghe các kết nối mới. Nếu địa chỉ là

[1, 4, 9]
25 thì một địa chỉ tùy ý được chọn

authkey là khóa xác thực sẽ được sử dụng để kiểm tra tính hợp lệ của các kết nối đến quy trình máy chủ. Nếu authkey là

[1, 4, 9]
25 thì
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
49 được sử dụng. Nếu không thì authkey được sử dụng và nó phải là một chuỗi byte

[1, 4, 9]
37 [[ trình khởi tạo [, initargs]]]

Bắt đầu một quy trình con để khởi động trình quản lý. Nếu trình khởi tạo không phải là

[1, 4, 9]
25 thì quy trình con sẽ gọi
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
52 khi nó bắt đầu

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
53 []

Trả về một đối tượng

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
54 đại diện cho máy chủ thực dưới sự kiểm soát của Trình quản lý. Đối tượng
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
54 hỗ trợ phương thức
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
56

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
3

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
54 còn có một thuộc tính

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
59 []

Kết nối đối tượng quản lý cục bộ với quy trình quản lý từ xa

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
4

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
60 []

Dừng quá trình được sử dụng bởi người quản lý. Điều này chỉ khả dụng nếu đã được sử dụng để bắt đầu quá trình máy chủ

Điều này có thể được gọi nhiều lần

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
62 [ typeid [ , có thể gọi được [, proxytype[, exposed[, method_to_typeid[, create_method]]]]]]

Một phương thức lớp có thể được sử dụng để đăng ký một loại hoặc có thể gọi được với lớp người quản lý

typeid là một "định danh loại" được sử dụng để xác định một loại đối tượng được chia sẻ cụ thể. Đây phải là một chuỗi

có thể gọi được là một có thể gọi được sử dụng để tạo các đối tượng cho loại định danh này. Nếu một phiên bản trình quản lý sẽ được kết nối với máy chủ bằng phương thức này hoặc nếu đối số create_method là

[1, 4, 9]
32 thì điều này có thể để lại là
[1, 4, 9]
25

proxytype là một lớp con được sử dụng để tạo proxy cho các đối tượng dùng chung với typeid này. Nếu

[1, 4, 9]
25 thì một lớp proxy được tạo tự động

được sử dụng để chỉ định một chuỗi tên phương thức mà proxy cho typeid này sẽ được phép truy cập bằng cách sử dụng. [Nếu tiếp xúc là

[1, 4, 9]
25 thì thay vào đó sử dụng
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
70 nếu nó tồn tại. ] Trong trường hợp không có danh sách hiển thị nào được chỉ định, tất cả các “phương thức công khai” của đối tượng được chia sẻ sẽ có thể truy cập được. [Ở đây “phương thức công khai” có nghĩa là bất kỳ thuộc tính nào có phương thức và tên của nó không bắt đầu bằng
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
72. ]

method_to_typeid là ánh xạ được sử dụng để chỉ định kiểu trả về của các phương thức được hiển thị đó sẽ trả về proxy. Nó ánh xạ các tên phương thức thành các chuỗi typeid. [Nếu method_to_typeid là

[1, 4, 9]
25 thì
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
74 được sử dụng thay thế nếu nó tồn tại. ] Nếu tên của phương thức không phải là khóa của ánh xạ này hoặc nếu ánh xạ là
[1, 4, 9]
25 thì đối tượng được phương thức trả về sẽ được sao chép theo giá trị

create_method xác định xem một phương thức có nên được tạo với tên typeid có thể được sử dụng để báo cho quy trình máy chủ tạo một đối tượng dùng chung mới và trả về proxy cho nó hay không. Theo mặc định, nó là

[1, 4, 9]
31

các phiên bản cũng có một thuộc tính chỉ đọc

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
78

Địa chỉ được sử dụng bởi người quản lý

Đã thay đổi trong phiên bản 3. 3. Các đối tượng trình quản lý hỗ trợ giao thức quản lý ngữ cảnh – xem. starts the server process [if it has not already started] and then returns the manager object. cuộc gọi.

Trong các phiên bản trước không bắt đầu quy trình máy chủ của người quản lý nếu nó chưa được bắt đầu

lớp
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
43
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
84

Một lớp con có thể được sử dụng để đồng bộ hóa các quy trình. Các đối tượng thuộc loại này được trả về bởi

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
86

Các phương thức của nó tạo và trả về một số loại dữ liệu thường được sử dụng để được đồng bộ hóa giữa các quy trình. Điều này đáng chú ý bao gồm các danh sách và từ điển được chia sẻ

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
00 [ các bên [ , hành động [, timeout]]]

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

Mới trong phiên bản 3. 3

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
03 [[ giá trị ]]

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
10 [[ khóa ]]

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

Nếu lock được cung cấp thì nó phải là proxy cho một hoặc đối tượng

Đã thay đổi trong phiên bản 3. 3. Phương thức đã được thêm vào.

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
17 []

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
20 []

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
00 []

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
30 [[ kích thước tối đa ]]

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
45 []

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
64 [[ giá trị ]]

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
93 [ mã loại, trình tự ]

Tạo một mảng và trả về một proxy cho nó

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
83 [ mã loại, giá trị ]

Tạo một đối tượng có thuộc tính

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
12 có thể ghi và trả về một proxy cho đối tượng đó

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
11 []
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
11 [mapping]
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
11[sequence]

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
15 []
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
15 [sequence]

Tạo một đối tượng được chia sẻ và trả lại proxy cho nó

Đã thay đổi trong phiên bản 3. 6. Các đối tượng được chia sẻ có khả năng được lồng vào nhau. Ví dụ: một đối tượng vùng chứa được chia sẻ như danh sách được chia sẻ có thể chứa các đối tượng được chia sẻ khác, tất cả sẽ được quản lý và đồng bộ hóa bởi.

lớp
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
43____8_______00

Một loại có thể đăng ký với

Một đối tượng không gian tên không có phương thức công khai, nhưng có các thuộc tính có thể ghi. Đại diện của nó cho thấy các giá trị của các thuộc tính của nó

Tuy nhiên, khi sử dụng proxy cho một đối tượng không gian tên, thuộc tính bắt đầu bằng

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
72 sẽ là thuộc tính của proxy chứ không phải thuộc tính của tham chiếu

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
5

17. 2. 2. 7. 1. người quản lý tùy chỉnh

Để tạo trình quản lý của riêng mình, người ta tạo một lớp con và sử dụng phương thức lớp để đăng ký các loại hoặc khả năng gọi mới với lớp trình quản lý. Ví dụ

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
6

17. 2. 2. 7. 2. Sử dụng trình quản lý từ xa

Có thể chạy máy chủ quản lý trên một máy và để khách hàng sử dụng nó từ các máy khác [giả sử rằng tường lửa có liên quan cho phép điều đó]

Chạy các lệnh sau sẽ tạo một máy chủ cho một hàng đợi được chia sẻ mà các máy khách từ xa có thể truy cập

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
7

Một khách hàng có thể truy cập máy chủ như sau

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
8

Một khách hàng khác cũng có thể sử dụng nó

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
9

Các quy trình cục bộ cũng có thể truy cập hàng đợi đó, sử dụng mã từ phía trên trên máy khách để truy cập từ xa

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
0

17. 2. 2. 8. Đối tượng ủy nhiệm

Proxy là một đối tượng đề cập đến một đối tượng được chia sẻ tồn tại [có lẽ] trong một quy trình khác. Đối tượng được chia sẻ được cho là tham chiếu của proxy. Nhiều đối tượng proxy có thể có cùng một tham chiếu

Một đối tượng proxy có các phương thức gọi các phương thức tương ứng của tham chiếu của nó [mặc dù không phải mọi phương thức của tham chiếu đều nhất thiết phải có sẵn thông qua proxy]. Bằng cách này, một proxy có thể được sử dụng giống như người tham chiếu của nó có thể

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
1

Lưu ý rằng việc áp dụng cho proxy sẽ trả về đại diện của tham chiếu, trong khi áp dụng sẽ trả về đại diện của proxy

Một tính năng quan trọng của các đối tượng proxy là chúng có thể chọn được để chúng có thể được chuyển giữa các quy trình. Như vậy, một tham chiếu có thể chứa. Điều này cho phép lồng các danh sách được quản lý này, các lệnh và các danh sách khác

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
2

Tương tự, proxy dict và list có thể được lồng vào nhau

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
3

Nếu tiêu chuẩn [không phải proxy] hoặc các đối tượng được chứa trong một tham chiếu, các sửa đổi đối với các giá trị có thể thay đổi đó sẽ không được truyền qua trình quản lý vì proxy không có cách nào biết khi nào các giá trị chứa bên trong được sửa đổi. Tuy nhiên, việc lưu trữ một giá trị trong proxy vùng chứa [kích hoạt

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
29 trên đối tượng proxy] sẽ lan truyền qua trình quản lý và do đó, để sửa đổi mục đó một cách hiệu quả, người ta có thể gán lại giá trị đã sửa đổi cho proxy vùng chứa

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
4

Cách tiếp cận này có lẽ kém thuận tiện hơn so với sử dụng lồng nhau cho hầu hết các trường hợp sử dụng nhưng cũng thể hiện mức độ kiểm soát đồng bộ hóa

Ghi chú

Các loại proxy không làm gì để hỗ trợ so sánh theo giá trị. Vì vậy, ví dụ, chúng ta có

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
5

Thay vào đó, người ta chỉ nên sử dụng một bản sao của người giới thiệu khi so sánh

lớp
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
43____8_______32

Các đối tượng proxy là các thể hiện của các lớp con của

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
34 [ tên phương thức [ , lập luận [, kwds]]]

Gọi và trả về kết quả của một phương thức tham chiếu của proxy

Nếu

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
35 là proxy có tham chiếu là
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
36 thì biểu thức

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
6

sẽ đánh giá biểu thức

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
7

trong quy trình của nhà quản lý

Giá trị được trả về sẽ là bản sao kết quả của cuộc gọi hoặc proxy cho một đối tượng được chia sẻ mới – xem tài liệu về đối số method_to_typeid của

Nếu một ngoại lệ được đưa ra bởi cuộc gọi, thì nó sẽ được đưa ra lại bởi. Nếu một số ngoại lệ khác được đưa ra trong quy trình của người quản lý thì điều này được chuyển thành ngoại lệ

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
39 và được đưa ra bởi

Note in particular that an exception will be raised if methodname has not been exposed

Một ví dụ về việc sử dụng

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
8

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
42 []

Return a copy of the referent

If the referent is unpicklable then this will raise an exception

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
43 []

Return a representation of the proxy object

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
44 []

Return the representation of the referent

17. 2. 2. 8. 1. Cleanup

A proxy object uses a weakref callback so that when it gets garbage collected it deregisters itself from the manager which owns its referent

A shared object gets deleted from the manager process when there are no longer any proxies referring to it

17. 2. 2. 9. Process Pools

One can create a pool of processes which will carry out tasks submitted to it with the class

class
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
46
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
47 [[ processes [ , initializer [ , initargs [ , maxtasksperchild [ , context ]]]]]]

A process pool object which controls a pool of worker processes to which jobs can be submitted. It supports asynchronous results with timeouts and callbacks and has a parallel map implementation

quy trình là số lượng quy trình công nhân để sử dụng. If processes is

[1, 4, 9]
25 then the number returned by is used

If initializer is not

[1, 4, 9]
25 then each worker process will call
import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
52 when it starts

maxtasksperchild is the number of tasks a worker process can complete before it will exit and be replaced with a fresh worker process, to enable unused resources to be freed. The default maxtasksperchild is

[1, 4, 9]
25, which means worker processes will live as long as the pool

context can be used to specify the context used for starting the worker processes. Usually a pool is created using the function

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
53 or the method of a context object. In both cases context is set appropriately

Note that the methods of the pool object should only be called by the process which created the pool

New in version 3. 2. maxtasksperchild

New in version 3. 4. context

Ghi chú

Worker processes within a typically live for the complete duration of the Pool’s work queue. A frequent pattern found in other systems [such as Apache, mod_wsgi, etc] to free resources held by workers is to allow a worker within a pool to complete only a set amount of work before being exiting, being cleaned up and a new process spawned to replace the old one. The maxtasksperchild argument to the exposes this ability to the end user

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
57 [ func [ , lập luận [, kwds]]]

Call func with arguments args and keyword arguments kwds. Nó chặn cho đến khi kết quả sẵn sàng. Given this blocks, is better suited for performing work in parallel. Additionally, func is only executed in one of the workers of the pool

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
59 [ func [ , args [ , kwds [ , callback [ , error_callback ]]]]]

A variant of the method which returns a result object

If callback is specified then it should be a callable which accepts a single argument. When the result becomes ready callback is applied to it, that is unless the call failed, in which case the error_callback is applied instead

If error_callback is specified then it should be a callable which accepts a single argument. If the target function fails, then the error_callback is called with the exception instance

Callbacks should complete immediately since otherwise the thread which handles the results will get blocked

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
61 [ func, iterable [ , chunksize ]]

A parallel equivalent of the built-in function [it supports only one iterable argument though]. It blocks until the result is ready

This method chops the iterable into a number of chunks which it submits to the process pool as separate tasks. The [approximate] size of these chunks can be specified by setting chunksize to a positive integer

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
63 [ func, iterable [ , chunksize [ , callback [ , error_callback ]]]]

A variant of the method which returns a result object

If callback is specified then it should be a callable which accepts a single argument. When the result becomes ready callback is applied to it, that is unless the call failed, in which case the error_callback is applied instead

If error_callback is specified then it should be a callable which accepts a single argument. If the target function fails, then the error_callback is called with the exception instance

Callbacks should complete immediately since otherwise the thread which handles the results will get blocked

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
65 [ func, iterable [ , chunksize ]]

A lazier version of

The chunksize argument is the same as the one used by the method. For very long iterables using a large value for chunksize can make the job complete much faster than using the default value of

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
68

Also if chunksize is

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
68 then the
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
70 method of the iterator returned by the method has an optional timeout parameter.
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
72 will raise if the result cannot be returned within timeout seconds

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
74 [ func, iterable [ , chunksize ]]

The same as except that the ordering of the results from the returned iterator should be considered arbitrary. [Only when there is only one worker process is the order guaranteed to be “correct”. ]

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
76 [ func, iterable [ , chunksize ]]

Like except that the elements of the iterable are expected to be iterables that are unpacked as arguments

Hence an iterable of

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
78 results in
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
79

Mới trong phiên bản 3. 3

from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
80 [ func, iterable [ , chunksize [ , callback [ , error_callback ]]]]

A combination of and that iterates over iterable of iterables and calls func with the iterables unpacked. Returns a result object

Mới trong phiên bản 3. 3

[1, 4, 9]
72 []

Prevents any more tasks from being submitted to the pool. Once all the tasks have been completed the worker processes will exit

[1, 4, 9]
66 []

Stops the worker processes immediately without completing outstanding work. When the pool object is garbage collected will be called immediately

[1, 4, 9]
39 []

Wait for the worker processes to exit. One must call or before using

New in version 3. 3. Pool objects now support the context management protocol – see . returns the pool object, and calls .

class
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
46
from multiprocessing import Process, Queue

def f[q]:
    q.put[[42, None, 'hello']]

if __name__ == '__main__':
    q = Queue[]
    p = Process[target=f, args=[q,]]
    p.start[]
    print[q.get[]]    # prints "[42, None, 'hello']"
    p.join[]
94

The class of the result returned by and

from multiprocessing import Process

def f[name]:
    print['hello', name]

if __name__ == '__main__':
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
55 [[ timeout ]]

Return the result when it arrives. If timeout is not

[1, 4, 9]
25 and the result does not arrive within timeout seconds then is raised. If the remote call raised an exception then that exception will be reraised by

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
01 [[ timeout ]]

Wait until the result is available or until timeout seconds pass

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
02 []

Return whether the call has completed

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
03 []

Return whether the call completed without raising an exception. Will raise if the result is not ready

The following example demonstrates the use of a pool

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
9

17. 2. 2. 10. Listeners and Clients

Usually message passing between processes is done using queues or by using objects returned by

However, the module allows some extra flexibility. It basically gives a high level message oriented API for dealing with sockets or Windows named pipes. It also has support for digest authentication using the module, and for polling multiple connections at the same time

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
09
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
10 [ connection, authkey ]

Send a randomly generated message to the other end of the connection and wait for a reply

If the reply matches the digest of the message using authkey as the key then a welcome message is sent to the other end of the connection. Otherwise is raised

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
09
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
13 [ connection, authkey ]

Receive a message, calculate the digest of the message using authkey as the key, and then send the digest back

If a welcome message is not received, then is raised

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
09
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
16 [ address [ , family [ , authkey ]]]

Attempt to set up a connection to the listener which is using address address, returning a

Loại kết nối được xác định bởi đối số họ, nhưng điều này thường có thể được bỏ qua vì nó thường có thể được suy ra từ định dạng địa chỉ. [See ]

If authkey is given and not None, it should be a byte string and will be used as the secret key for an HMAC-based authentication challenge. No authentication is done if authkey is None. được nâng lên nếu xác thực không thành công. Thấy

class
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
09
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
20 [[ address [ , family [ , backlog [ , authkey ]]]]]

A wrapper for a bound socket or Windows named pipe which is ‘listening’ for connections

address is the address to be used by the bound socket or named pipe of the listener object

Ghi chú

Nếu một địa chỉ của '0. 0. 0. 0' được sử dụng, địa chỉ sẽ không phải là điểm cuối có thể kết nối trên Windows. Nếu bạn yêu cầu điểm cuối có thể kết nối, bạn nên sử dụng '127. 0. 0. 1’

family là loại ổ cắm [hoặc ống có tên] sẽ sử dụng. Đây có thể là một trong các chuỗi

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
21 [đối với ổ cắm TCP],
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
22 [đối với ổ cắm tên miền Unix] hoặc
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
23 [đối với đường ống có tên Windows]. Trong số này chỉ có cái đầu tiên được đảm bảo có sẵn. Nếu gia đình là
[1, 4, 9]
25 thì gia đình đó được suy ra từ dạng địa chỉ. Nếu địa chỉ cũng là
[1, 4, 9]
25 thì giá trị mặc định được chọn. Mặc định này là họ được coi là nhanh nhất hiện có. See . Note that if family is
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
22 and address is
[1, 4, 9]
25 then the socket will be created in a private temporary directory created using

If the listener object uses a socket then backlog [1 by default] is passed to the method of the socket once it has been bound

If authkey is given and not None, it should be a byte string and will be used as the secret key for an HMAC-based authentication challenge. No authentication is done if authkey is None. được nâng lên nếu xác thực không thành công. Thấy

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
31 []

Accept a connection on the bound socket or named pipe of the listener object and return a object. If authentication is attempted and fails, then is raised

[1, 4, 9]
72 []

Close the bound socket or named pipe of the listener object. Điều này được gọi tự động khi người nghe được thu gom rác. However it is advisable to call it explicitly

Các đối tượng người nghe có các thuộc tính chỉ đọc sau

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
78

The address which is being used by the Listener object

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
36

The address from which the last accepted connection came. If this is unavailable then it is

[1, 4, 9]
25

New in version 3. 3. Listener objects now support the context management protocol – see . returns the listener object, and calls .

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
09
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
01 [ object_list, timeout=None ]

Wait till an object in object_list is ready. Returns the list of those objects in object_list which are ready. If timeout is a float then the call blocks for at most that many seconds. If timeout is

[1, 4, 9]
25 then it will block for an unlimited period. A negative timeout is equivalent to a zero timeout

For both Unix and Windows, an object can appear in object_list if it is

  • a readable object;
  • a connected and readable object; or
  • the attribute of a object

A connection or socket object is ready when there is data available to be read from it, or the other end has been closed

Unix.

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
48 almost equivalent
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
49. The difference is that, if is interrupted by a signal, it can raise with an error number of
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
52, whereas will not

Windows. An item in object_list must either be an integer handle which is waitable [according to the definition used by the documentation of the Win32 function

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
54] or it can be an object with a
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
55 method which returns a socket handle or pipe handle. [Note that pipe handles and socket handles are not waitable handles. ]

Mới trong phiên bản 3. 3

Examples

The following server code creates a listener which uses

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
56 as an authentication key. It then waits for a connection and sends some data to the client

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
0

The following code connects to the server and receives some data from the server

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
1

The following code uses to wait for messages from multiple processes at once

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
2

17. 2. 2. 10. 1. Address Formats

  • An
    from multiprocessing import Process, Pipe
    
    def f[conn]:
        conn.send[[42, None, 'hello']]
        conn.close[]
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe[]
        p = Process[target=f, args=[child_conn,]]
        p.start[]
        print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
        p.join[]
    
    21 address is a tuple of the form
    from multiprocessing import Process, Pipe
    
    def f[conn]:
        conn.send[[42, None, 'hello']]
        conn.close[]
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe[]
        p = Process[target=f, args=[child_conn,]]
        p.start[]
        print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
        p.join[]
    
    59 where hostname is a string and port is an integer
  • An
    from multiprocessing import Process, Pipe
    
    def f[conn]:
        conn.send[[42, None, 'hello']]
        conn.close[]
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe[]
        p = Process[target=f, args=[child_conn,]]
        p.start[]
        print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
        p.join[]
    
    22 address is a string representing a filename on the filesystem
  • Một địa chỉ
    from multiprocessing import Process, Pipe
    
    def f[conn]:
        conn.send[[42, None, 'hello']]
        conn.close[]
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe[]
        p = Process[target=f, args=[child_conn,]]
        p.start[]
        print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
        p.join[]
    
    23 là một chuỗi có dạng_______4_______62. To use to connect to a named pipe on a remote computer called ServerName one should use an address of the form
    from multiprocessing import Process, Pipe
    
    def f[conn]:
        conn.send[[42, None, 'hello']]
        conn.close[]
    
    if __name__ == '__main__':
        parent_conn, child_conn = Pipe[]
        p = Process[target=f, args=[child_conn,]]
        p.start[]
        print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
        p.join[]
    
    64 instead

Note that any string beginning with two backslashes is assumed by default to be an

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
23 address rather than an
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
22 address

17. 2. 2. 11. Authentication keys

When one uses , the data received is automatically unpickled. Unfortunately unpickling data from an untrusted source is a security risk. Therefore and use the module to provide digest authentication

An authentication key is a byte string which can be thought of as a password. once a connection is established both ends will demand proof that the other knows the authentication key. [Demonstrating that both ends are using the same key does not involve sending the key over the connection. ]

If authentication is requested but no authentication key is specified then the return value of

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
49 is used [see ]. Giá trị này sẽ được tự động kế thừa bởi bất kỳ đối tượng nào mà quy trình hiện tại tạo ra. This means that [by default] all processes of a multi-process program will share a single authentication key which can be used when setting up connections between themselves

Suitable authentication keys can also be generated by using

17. 2. 2. 12. Logging

Some support for logging is available. Note, however, that the package does not use process shared locks so it is possible [depending on the handler type] for messages from different processes to get mixed up

[1, 4, 9]
21
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
77 []

Returns the logger used by . If necessary, a new one will be created

When first created the logger has level

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
79 and no default handler. Messages sent to this logger will not by default propagate to the root logger

Note that on Windows child processes will only inherit the level of the parent process’s logger – any other customization of the logger will not be inherited

[1, 4, 9]
21
from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
81 []

This function performs a call to but in addition to returning the logger created by get_logger, it adds a handler which sends output to using format

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
84

Below is an example session with logging turned on

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
3

For a full table of logging levels, see the module

17. 2. 2. 13. The module

replicates the API of but is no more than a wrapper around the module

17. 2. 3. Programming guidelines

There are certain guidelines and idioms which should be adhered to when using

17. 2. 3. 1. All start methods

The following applies to all start methods

Avoid shared state

As far as possible one should try to avoid shifting large amounts of data between processes

It is probably best to stick to using queues or pipes for communication between processes rather than using the lower level synchronization primitives

Picklability

Ensure that the arguments to the methods of proxies are picklable

Thread safety of proxies

Do not use a proxy object from more than one thread unless you protect it with a lock

[There is never a problem with different processes using the same proxy. ]

Joining zombie processes

On Unix when a process finishes but has not been joined it becomes a zombie. There should never be very many because each time a new process starts [or is called] all completed processes which have not yet been joined will be joined. Also calling a finished process’s will join the process. Even so it is probably good practice to explicitly join all the processes that you start

Better to inherit than pickle/unpickle

When using the spawn or forkserver start methods many types from need to be picklable so that child processes can use them. However, one should generally avoid sending shared objects to other processes using pipes or queues. Instead you should arrange the program so that a process which needs access to a shared resource created elsewhere can inherit it from an ancestor process

Avoid terminating processes

Using the method to stop a process is liable to cause any shared resources [such as locks, semaphores, pipes and queues] currently being used by the process to become broken or unavailable to other processes

Therefore it is probably best to only consider using on processes which never use any shared resources

Joining processes that use queues

Bear in mind that a process that has put items in a queue will wait before terminating until all the buffered items are fed by the “feeder” thread to the underlying pipe. [The child process can call the method of the queue to avoid this behaviour. ]

This means that whenever you use a queue you need to make sure that all items which have been put on the queue will eventually be removed before the process is joined. Otherwise you cannot be sure that processes which have put items on the queue will terminate. Remember also that non-daemonic processes will be joined automatically

An example which will deadlock is the following

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
4

A fix here would be to swap the last two lines [or simply remove the

from multiprocessing import Process, Pipe

def f[conn]:
    conn.send[[42, None, 'hello']]
    conn.close[]

if __name__ == '__main__':
    parent_conn, child_conn = Pipe[]
    p = Process[target=f, args=[child_conn,]]
    p.start[]
    print[parent_conn.recv[]]   # prints "[42, None, 'hello']"
    p.join[]
97 line]

Explicitly pass resources to child processes

On Unix using the fork start method, a child process can make use of a shared resource created in a parent process using a global resource. However, it is better to pass the object as an argument to the constructor for the child process

Apart from making the code [potentially] compatible with Windows and the other start methods this also ensures that as long as the child process is still alive the object will not be garbage collected in the parent process. This might be important if some resource is freed when the object is garbage collected in the parent process

So for instance

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
5

should be rewritten as

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
6

Beware of replacing with a “file like object”

originally unconditionally called

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
7

in the

from multiprocessing import Process, Lock

def f[l, i]:
    l.acquire[]
    try:
        print['hello world', i]
    finally:
        l.release[]

if __name__ == '__main__':
    lock = Lock[]

    for num in range[10]:
        Process[target=f, args=[lock, num]].start[]
00 method — this resulted in issues with processes-in-processes. This has been changed to

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
8

Which solves the fundamental issue of processes colliding with each other resulting in a bad file descriptor error, but introduces a potential danger to applications which replace with a “file-like object” with output buffering. Mối nguy hiểm này là nếu nhiều quá trình gọi đối tượng giống như tệp này, nó có thể dẫn đến cùng một dữ liệu được chuyển sang đối tượng nhiều lần, dẫn đến hỏng

If you write a file-like object and implement your own caching, you can make it fork-safe by storing the pid whenever you append to the cache, and discarding the cache when the pid changes. For example

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    mp.set_start_method['spawn']
    q = mp.Queue[]
    p = mp.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
9

Để biết thêm thông tin, hãy xem bpo-5155, bpo-5313 và bpo-5331

17. 2. 3. 2. Các phương thức bắt đầu spawn và forkserver

There are a few extra restriction which don’t apply to the fork start method

More picklability

Ensure that all arguments to

[1, 4, 9]
34 are picklable. Also, if you subclass then make sure that instances will be picklable when the method is called

Global variables

Bear in mind that if code run in a child process tries to access a global variable, then the value it sees [if any] may not be the same as the value in the parent process at the time that was called

However, global variables which are just module level constants cause no problems

Safe importing of main module

Make sure that the main module can be safely imported by a new Python interpreter without causing unintended side effects [such a starting a new process]

For example, using the spawn or forkserver start method running the following module would fail with a

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
0

Thay vào đó, người ta nên bảo vệ “điểm đầu vào” của chương trình bằng cách sử dụng

from multiprocessing import Process, Lock

def f[l, i]:
    l.acquire[]
    try:
        print['hello world', i]
    finally:
        l.release[]

if __name__ == '__main__':
    lock = Lock[]

    for num in range[10]:
        Process[target=f, args=[lock, num]].start[]
08 như sau

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
1

[The

from multiprocessing import Process
import os

def info[title]:
    print[title]
    print['module name:', __name__]
    print['parent process:', os.getppid[]]
    print['process id:', os.getpid[]]

def f[name]:
    info['function f']
    print['hello', name]

if __name__ == '__main__':
    info['main line']
    p = Process[target=f, args=['bob',]]
    p.start[]
    p.join[]
16 line can be omitted if the program will be run normally instead of frozen. ]

This allows the newly spawned Python interpreter to safely import the module and then run the module’s

from multiprocessing import Process, Lock

def f[l, i]:
    l.acquire[]
    try:
        print['hello world', i]
    finally:
        l.release[]

if __name__ == '__main__':
    lock = Lock[]

    for num in range[10]:
        Process[target=f, args=[lock, num]].start[]
10 function

Similar restrictions apply if a pool or manager is created in the main module

17. 2. 4. Examples

Demonstration of how to create and use customized managers and proxies

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
2

Using

import multiprocessing as mp

def foo[q]:
    q.put['hello']

if __name__ == '__main__':
    ctx = mp.get_context['spawn']
    q = ctx.Queue[]
    p = ctx.Process[target=foo, args=[q,]]
    p.start[]
    print[q.get[]]
    p.join[]
3

An example showing how to use queues to feed tasks to a collection of worker processes and collect the results

Does Python multiprocessing use shared memory?

multiprocessing is a drop in replacement for Python's multiprocessing module. It supports the exact same operations, but extends it, so that all tensors sent through a multiprocessing. Queue , will have their data moved into shared memory and will only send a handle to another process.

How does shared memory work in Python?

Shared memory can be a very efficient way of handling data in a program that uses concurrency. Python's mmap uses shared memory to efficiently share large amounts of data between multiple Python processes, threads, and tasks that are happening concurrently .

Can multiprocessing access global variables?

You can inherit global variables between forked processes, but not spawned processes .

Can Python multiprocessing access global variables?

You can share a global variable with all child workers processes in the multiprocessing pool by defining it in the worker process initialization function . In this tutorial you will discover how to share global variables with all workers in the Python process pool.

Chủ Đề