Mô-đun này không hoạt động hoặc không khả dụng trên nền tảng WebAssugging
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[]7 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[]8. Xem để biết thêm thông tin
Giới thiệu
là gói hỗ trợ các quy trình sinh sản bằng API tương tự như mô-đun. Gói cung cấp cả đồng thời cục bộ và từ xa, hỗ trợ hiệu quả bằng cách sử dụng các quy trình con thay vì các luồng. Do đó, mô-đun cho phép lập trình viên tận dụng tối đa nhiều bộ xử lý trên một máy nhất định. Nó chạy trên cả Unix và Windows
Mô-đun này cũng giới thiệu các API không có tương tự trong mô-đun. Một ví dụ điển hình của điều này là đối tượng cung cấp một phương tiện thuận tiện để song song hóa việc thực thi một hàm trên nhiều giá trị đầu vào, phân phối dữ liệu đầu vào qua các quy trình [song song hóa dữ liệu]. Ví dụ sau minh họa cách thực hành phổ biến để xác định các chức năng như vậy trong một mô-đun để các quy trình con có thể nhập thành công mô-đun đó. Ví dụ cơ bản này về tính song song dữ liệu bằng cách sử dụng,
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]
Xem thêm
cung cấp giao diện cấp cao hơn để đẩy các tác vụ sang quy trình nền mà không chặn thực thi quy trình gọi. So với việc sử dụng giao diện trực tiếp, API dễ dàng hơn cho phép gửi công việc đến nhóm quy trình cơ bản để tách biệt khỏi việc chờ đợi kết quả
Lớp
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[]6 part is necessary, see
Contexts and start methods
Depending on the platform, supports three ways to start a process. These start methods are
đẻ trứng
The parent process starts a fresh Python interpreter process. The child process will only inherit those resources necessary to run the process object’s method. In particular, unnecessary file descriptors and handles from the parent process will not be inherited. Starting a process using this method is rather slow compared to using fork or forkserver
Available on Unix and Windows. The default on Windows and macOS
forkThe parent process uses to fork the Python interpreter. The child process, when it begins, is effectively identical to the parent process. All resources of the parent are inherited by the child process. Note that safely forking a multithreaded process is problematic
Available on Unix only. The default on Unix
forkserverKhi 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
Có sẵn trên các nền tảng Unix hỗ trợ chuyển bộ mô tả tệp qua các đường ống Unix
Đã thay đổi trong phiên bản 3. 8. Trên macOS, phương thức bắt đầu sinh sản hiện là mặc định. Phương pháp bắt đầu ngã ba nên được coi là không an toàn vì nó có thể dẫn đến sự cố của quy trình con. Xem bpo-33725.
Đã thay đổi trong phiên bản 3. 4. đã thêm spawn trên tất cả các nền tảng Unix và thêm máy chủ phân nhánh cho một số nền tảng Unix. Các tiến trình con không còn kế thừa tất cả các xử lý có thể kế thừa của cha mẹ trên Windows.
Trên Unix, việc sử dụng các phương thức khởi động spawn hoặc forkserver cũng sẽ bắt đầu một quy trình theo dõi tài nguyên theo dõi các tài nguyên hệ thống được đặt tên chưa được liên kết [chẳng hạn như các đối tượng hoặc semaphores được đặt tên] được tạo bởi các quy trình của chương trình. Khi tất cả các quy trình đã thoát, trình theo dõi tài nguyên sẽ hủy liên kết mọi đối tượng được theo dõi còn lại. Thông thường sẽ không có, nhưng nếu một quá trình bị giết bởi một tín hiệu thì có thể có một số tài nguyên "bị rò rỉ". [Các semaphore bị rò rỉ cũng như các phân đoạn bộ nhớ dùng chung sẽ không được tự động hủy liên kết cho đến lần khởi động lại tiếp theo. Đây là vấn đề đối với cả hai đối tượng vì hệ thống chỉ cho phép một số lượng hạn chế các semaphores được đặt tên và các phân đoạn bộ nhớ dùng chung chiếm một số không gian trong bộ nhớ chính. ]
Để chọn phương thức bắt đầu, bạn sử dụng mệnh đề 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[]6 của mô-đun chính. Ví dụ
________số 8_______
không nên được sử dụng nhiều hơn một lần trong chương trình
Ngoài ra, bạn có thể sử dụng để có được một đối tượng bối cảnh. Các đối tượng ngữ cảnh có API giống như mô-đun đa xử lý và cho phép một người sử dụng nhiều phương thức bắt đầu trong cùng một chương trì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[]
Lưu ý rằng các đối tượng liên quan đến một bối cảnh có thể không tương thích với các quy trình cho một bối cảnh khác. Cụ thể, các khóa được tạo bằng bối cảnh ngã ba không thể được chuyển đến các quy trình được bắt đầu bằng phương pháp bắt đầu sinh sản hoặc máy chủ ngã ba
Một thư viện muốn sử dụng một phương thức bắt đầu cụ thể có lẽ nên sử dụng để tránh can thiệp vào sự lựa chọn của người dùng thư viện
Cảnh báo
Các phương thức bắt đầu
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[]7 và
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[]8 hiện không thể được sử dụng với các tệp thực thi "đóng băng" [i. e. , các tệp nhị phân được tạo bởi các gói như PyInstaller và cx_Freeze] trên Unix. Phương pháp bắt đầu
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[]9 hoạt động
Trao đổi đối tượng giữa các tiến trình
hỗ trợ hai loại kênh liên lạc giữa các quy trình
hàng đợi
Lớp học là một bản sao gần như của. Ví dụ
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[]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ó các phương thức
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 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[:]]6 [trong số các phương thức 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
Đồ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
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]0Các đối số
[1, 4, 9]02 và[1, 4, 9]03 được sử dụng khi tạo[1, 4, 9]04 và[1, 4, 9]05 là các loại mã được sử dụng bởi mô-đun.[1, 4, 9]02 biểu thị số float có độ chính xác kép và[1, 4, 9]03 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 các điều khiển 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
Trình quản lý được trả về sẽ hỗ trợ các loại , , , , , , , , , , , và. Ví dụ,
[1, 4, 9]1sẽ in
[1, 4, 9]2Trì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
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]26. Đ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 đủ được xen kẽ theo kiểu bán ngẫu nhiên, và sau đó bạn có thể phải dừng quá trình gốc bằng cách nào đó. ]
Reference
Gói chủ yếu sao chép API của mô-đun
và ngoại lệ
lớp đa xử lý. Quy trình[nhóm=Không, target=None, name=None, args=[], kwargs={}, *, daemon=None]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]33; . 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]33, nghĩa là không có gì được gọi. tên là tên quy trình [xem để biết thêm chi tiết]. 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]39 hoặc
[1, 4, 9]40. Nếu
[1, 4, 9]33 [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. Đối số args, mặc định là
[1, 4, 9]42, có thể được sử dụng để chỉ định danh sách hoặc bộ đối số sẽ 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]43] 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.
chạy[]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
Sử dụng một danh sách hoặc bộ dữ liệu làm đối số args được truyền để đạt được hiệu quả tương tự
Ví dụ
[1, 4, 9]5bắt đầu[]
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
tham gia[[hết thời gian]]Nếu thời gian chờ đối số tùy chọn là
[1, 4, 9]33 [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]33 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
tênTên quy trình. Tên là một chuỗi chỉ được sử dụng cho mục đích nhận dạng. Nó không có ngữ nghĩa. Nhiều quá trình có thể được đặt tên giống nhau
Tên ban đầu được đặt bởi hàm tạo. Nếu không có tên rõ ràng nào được cung cấp cho hàm tạo, tên có dạng 'Process-N1. N2. …. Nk' được xây dựng, trong đó mỗi Nk là con thứ N của cha mẹ của nó
is_alive[]Trả về xem quá trình có còn hoạt động không
Đại khái, một đối tượng quá trình tồn tại từ thời điểm phương thức trả về cho đến khi quá trình con kết thúc
yêu tinhThe process’s daemon flag, a Boolean value. Điều này phải được thiết lập trước khi được gọi là
Giá trị ban đầu được kế thừa từ quá trình tạo
Khi một tiến trình thoát, nó sẽ cố gắng chấm dứt tất cả các tiến trình con daemon của nó
Lưu ý rằng quy trình daemon không được phép tạo quy trình con. Mặt khác, một quy trình daemon sẽ khiến các con của nó mồ côi nếu nó bị chấm dứt khi quá trình cha mẹ của nó thoát ra. Ngoài ra, đây không phải là dịch vụ hoặc daemon Unix, chúng là các quy trình bình thường sẽ bị chấm dứt [và không được tham gia] nếu các quy trình không phải daemon đã thoát
Ngoài API, các đối tượng cũng hỗ trợ các thuộc tính và phương thức sau
pidTrả lại ID tiến trình. Trước khi quá trình được sinh ra, đây sẽ là
[1, 4, 9]33mã thoát
The child’s exit code. Đây sẽ là
[1, 4, 9]33 nếu quá trình chưa kết thúc
Nếu phương thức của con trả về bình thường, mã thoát sẽ là 0. Nếu nó kết thúc bằng một đối số nguyên N, mã thoát sẽ là N
Nếu đứa trẻ bị chấm dứt do một ngoại lệ không bị bắt trong , mã thoát sẽ là 1. Nếu nó bị kết thúc bởi tín hiệu N, mã thoát sẽ là giá trị âm -N
authkeyKhó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
When a object is created, it will inherit the authentication key of its parent process, although this may be changed by setting to another byte string
Nhìn thấy
lính gácMộ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. Otherwise calling is simpler
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]66 và
[1, 4, 9]67. 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
terminate[]Chấm dứt quá trình. Trên Unix, điều này được thực hiện bằng tín hiệu
[1, 4, 9]69; . Note that exit handlers and finally clauses, etc. , will not be executed
Lưu ý rằng các tiến trình con của tiến trình sẽ không bị chấm dứt – chúng sẽ đơn giản trở nên mồ côi
Cảnh báo
If this method is used when the associated process is using a pipe or queue then the pipe or queue is liable to become corrupted and may become unusable by other process. 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
kill[]Tương tự nhưng sử dụng tín hiệu
[1, 4, 9]72 trên Unix
Mới trong phiên bản 3. 7
đóng[]Đó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
Note that the , , , and methods should only be called by the process that created the process object
Ví dụ sử dụng một số phương pháp của
[1, 4, 9]6ngoại lệ đa xử lý. Lỗi quy trình
Lớp cơ sở của tất cả các ngoại lệ
exception multiprocessing. BufferTooShortNgoại lệ được đưa ra bởi
[1, 4, 9]85 khi đối tượng bộ đệm được cung cấp quá nhỏ để đọc thông báo
If
[1, 4, 9]86 is an instance of then
[1, 4, 9]88 will give the message as a byte stringngoại lệ đa xử lý. Lỗi xác thực
Xảy ra khi có lỗi xác thực
ngoại lệ đa xử lý. Lỗi hết giờTăng theo các phương thức có thời gian chờ khi hết thời gian chờ
Đườ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. 5’s class
If you use then you must call for each task removed from the queue or else the semaphore used to count the number of unfinished tasks may eventually overflow, raising an exception
Note that one can also create a shared queue by using a manager object – see
Ghi chú
uses the usual and exceptions to signal a timeout. They are not available in the namespace so you need to import them from
Ghi chú
When an object is put on a queue, the object is pickled and a background thread later flushes the pickled data to an underlying pipe. This has some consequences which are a little surprising, but should not cause any practical difficulties – if they really bother you then you can instead use a queue created with a
After putting an object on an empty queue there may be an infinitesimal delay before the queue’s method returns and can return without raising
If multiple processes are enqueuing objects, it is possible for the objects to be received at the other end out-of-order. However, objects enqueued by the same process will always be in the expected order with respect to each other
Cảnh báo
If a process is killed using or while it is trying to use a , then the data in the queue is likely to become corrupted. This may cause any other process to get an exception when it tries to use the queue later on
Cảnh báo
As mentioned above, if a child process has put items on a queue [and it has not used ], then that process will not terminate until all buffered items have been flushed to the pipe
This means that if you try joining that process you may get a deadlock unless you are sure that all items which have been put on the queue have been consumed. Similarly, if the child process is non-daemonic then the parent process may hang on exit when it tries to join all its non-daemonic children
Note that a queue created using a manager does not have this issue. See
For an example of the usage of queues for interprocess communication see
multiprocessing. Pipe[[duplex]]Returns a pair
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]13 of objects representing the ends of a pipe
If duplex is
[1, 4, 9]39 [the default] then the pipe is bidirectional. If duplex is
[1, 4, 9]40 then the pipe is unidirectional.
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]17 can only be used for receiving messages and
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]18 can only be used for sending messagesclass multiprocessing. Queue[[maxsize]]
Returns a process shared queue implemented using a pipe and a few locks/semaphores. When a process first puts an item on the queue a feeder thread is started which transfers objects from a buffer into the pipe
The usual and exceptions from the standard library’s module are raised to signal timeouts
implements all the methods of except for and
qsize[]Return the approximate size of the queue. Because of multithreading/multiprocessing semantics, this number is not reliable
Note that this may raise on Unix platforms like macOS where
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]27 is not implemented
Return
[1, 4, 9]39 if the queue is empty,
[1, 4, 9]40 otherwise. Because of multithreading/multiprocessing semantics, this is not reliablefull[]
Return
[1, 4, 9]39 if the queue is full,
[1, 4, 9]40 otherwise. Because of multithreading/multiprocessing semantics, this is not reliableput[obj[ , block[ , timeout]]]
Put obj into the queue. Nếu khối đối số tùy chọn là
[1, 4, 9]39 [mặc định] và thời gian chờ là
[1, 4, 9]33 [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]40], đặ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 đó]
Đã thay đổi trong phiên bản 3. 8. Nếu hàng đợi đã đóng, sẽ được nâng lên thay vì.
put_nowait[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[]39nhận[[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]39 [mặc định] và thời gian chờ là
[1, 4, 9]33 [mặc định], hãy chặn nếu cần 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]40], 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 đó]
Đã thay đổi trong phiên bản 3. 8. Nếu hàng đợi đã đóng, sẽ được nâng lên thay vì.
get_nowait[]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[]47
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ã
đóng[]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
join_thread[]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. The process can call to make do nothing
cancel_join_thread[]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[]55. 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 đa xử lý. Queue đơn giảnNó là một loại đơn giản hóa, rất gần với một khóa
đóng[]Đóng hàng đợi. giải phóng nội lực
Một hàng đợi không được sử dụng nữa sau khi nó bị đóng. Ví dụ: và các phương thức không còn được gọi nữa
Mới trong phiên bản 3. 9
empty[]Trả lại
[1, 4, 9]39 nếu hàng đợi trống, ngược lại là
[1, 4, 9]40get[]
Xóa và trả lại một mục khỏi hàng đợi
đặt[mục]Đặt mục vào hàng đợi
lớp đa xử lý. JoinableQueue[[maxsize]], một lớp con, là một hàng đợi có thêm và các phương thức
task_done[]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
tham gia[]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. When the count of unfinished tasks drops to zero, unblocks
Điều khoản khác
multiprocessing. active_children[]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
đa xử lý. cpu_count[]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. The number of usable CPUs can be obtained with
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]77
Khi không xác định được số lượng CPU a được nâng lên
Xem thêm
đa xử lý. current_ process[]Trả về đối tượng tương ứng với quy trình hiện tại
An analogue of
multiprocessing. parent_process[]Trả về đối tượng tương ứng với tiến trình cha của. Đối với quy trình chính,
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]84 sẽ là
[1, 4, 9]33
Mới trong phiên bản 3. 8
đa xử lý. freeze_support[]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[]6 của mô-đun chính. Ví dụ
[1, 4, 9]7
Nếu dòng
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]88 bị bỏ qua thì việc cố gắng chạy tệp thực thi bị đóng băng sẽ tăng
Calling
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]88 has no effect when invoked on any operating system other than 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 def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]88 không có hiệu lựcđa xử lý. get_all_start_methods[]
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. Các phương pháp bắt đầu có thể là
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[]9,
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[]7 và
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[]8. On Windows only
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[]7 is available. Trên Unix,
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[]9 và
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[]7 luôn được hỗ trợ, với
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[]9 là mặc định
Mới trong phiên bản 3. 4
đa xử lý. get_context[phương thức=Không]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]33 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, 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[]9,
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[]7,
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[]8. is raised if the specified start method is not available
Mới trong phiên bản 3. 4
multiprocessing. get_start_method[allow_none=Sai]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 bắt đầu chưa được sửa và allow_none là đúng thì trả về
[1, 4, 9]33
Giá trị trả về có thể là
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[]9,
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[]7,
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[]8 hoặc
[1, 4, 9]33.
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[]9 là mặc định trên Unix, trong khi
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[]7 là mặc định trên Windows và macOS
Đã thay đổi trong phiên bản 3. 8. Trên macOS, phương thức bắt đầu sinh sản hiện là mặc định. Phương pháp bắt đầu ngã ba nên được coi là không an toàn vì nó có thể dẫn đến sự cố của quy trình con. Xem bpo-33725.
Mới trong phiên bản 3. 4
đa xử lý. set_executable[có thể thực thi]Đặt đường dẫn của trình thông dịch Python để sử dụng khi bắt đầu 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]8
trước khi họ có thể tạo các tiến trình con
Changed in version 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, 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[]7.
Changed in version 3. 11. Chấp nhận một.
đa xử lý. set_start_method[phương thức , lực lượng=False]Đặt phương thức sẽ được sử dụng để bắt đầu các tiến trình con. Đối số phương pháp có thể là
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[]9,
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[]7 hoặc
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[]8. Tăng nếu phương thức bắt đầu đã được thiết lập và lực không phải là
[1, 4, 9]39. If method is
[1, 4, 9]33 and force is
[1, 4, 9]39 then the start method is set to
[1, 4, 9]33. If method is
[1, 4, 9]33 and force is
[1, 4, 9]40 then the context is set to the default context
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[]6 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
Đố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 đa xử lý. sự liên quan. Kết nốigửi[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. Very large pickles [approximately 32 MiB+, though it depends on the OS] may raise a exception
recv[]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
fileno[]Trả lại bộ mô tả tệp hoặc tay cầm được sử dụng bởi kết nối
đóng[]Close the connection
Điều này được gọi tự động khi kết nối được thu gom rác
thăm dò ý kiến[[hết thời gian]]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]33 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
send_bytes[bộ đệm[ , offset[, 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ệ
recv_byte[[độ 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.
recv_bytes_into[bộ đệm[ , offset]]Đọ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ệ
[1, 4, 9]87 sẽ được đưa ra và thông báo hoàn chỉnh có sẵn dưới dạng
[1, 4, 9]88 trong đó
[1, 4, 9]86 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]9
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
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, 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. Nhìn 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
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 đa xử lý. Rào cản[các bên[ , action[, 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 đa xử lý. BoundedSemaphore[[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
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[]60 của nó được đặt tên là khối, phù hợp với
Ghi chú
Trên macOS, đ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[]27 không được triển khai trên nền tảng đólớp đa xử lý. Điều kiện[[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 đa xử lý. Sự kiệnmột bản sao của
lớp đa xử lý. KhóaMộ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
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 đượ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
mua lại[chặn=Đúng, 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]39 [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]39. 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]40, 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]40;
Khi được gọi với giá trị dương, dấu chấm độ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]33 [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]33 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]40 và do đó bị bỏ qua. Trả về
[1, 4, 9]39 nếu khóa đã được lấy hoặc
[1, 4, 9]40 nếu hết thời gian chờphát hành[]
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 đa xử lý. RLockMộ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
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[]93 đượ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
mua lại[chặn=Đúng, 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]39, 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]39. 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]40, không chặn. Nếu khóa đã được mua [và do đó được sở hữu] bởi một quy trình hoặc luồng khác, thì quy trình hoặc luồng hiện tại không có quyền sở hữu và mức đệ quy trong khóa không bị thay đổi, dẫn đến giá trị trả về là
[1, 4, 9]40. 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]39
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
phát hành[]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 đa xử lý. Semaphore[[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
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[]60 của nó được đặt tên là khối, phù hợp với
Ghi chú
Trên macOS,
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[]09 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[]10 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 do Ctrl-C tạo ra xuất hiện trong khi luồng chính bị chặn bởi lệnh 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[]11, , ,
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[]14,
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[]15 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[]16 thì lệnh 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[]19 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
Đố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
đa xử lý. Giá trị[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]39 [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]40 thì quyền truy cập vào đối tượng được trả lại sẽ không được bảo vệ tự động bằng khóa, 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[]29 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
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]0
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[]1
Lưu ý rằng khóa là đối số chỉ có từ khóa
đa xử lý. Mảng[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]39 [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]40 thì quyền truy cập vào đối tượng được trả lại sẽ không được bảo vệ tự động bằng khóa, 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
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ố
đa xử lý. sharedctypes. RawArray[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
đa xử lý. sharedctypes. Giá trị thô[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__': mp.set_start_method['spawn'] q = mp.Queue[] p = mp.Process[target=foo, args=[q,]] p.start[] print[q.get[]] p.join[]44 và
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 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ềđa xử lý. sharedctypes. Mảng[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]39 [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]40 thì quyền truy cập vào đối tượng được trả lại sẽ không được bảo vệ tự động bằng khóa, 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
đa xử lý. sharedctypes. Giá trị[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]39 [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]40 thì quyền truy cập vào đối tượng được trả lại sẽ không được bảo vệ tự động bằng khóa, 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
đa xử lý. sharedctypes. bản sao[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
đa xử lý. sharedctypes. đồng bộ[obj[ , lock]]Trả về một đối tượng trình bao an toàn cho một đối tượng ctypes sử dụng khóa để đồng bộ hóa quyền truy cập. Nếu khóa là
[1, 4, 9]33 [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__': mp.set_start_method['spawn'] q = mp.Queue[] p = mp.Process[target=foo, args=[q,]] p.start[] print[q.get[]] p.join[]59 trả về đối tượng được bọc và
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[]60 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 thông thường. [Trong bảng
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[]61 là một phân lớp nào đó của. ]
ctypes
sharedctypes sử dụng loại
sharedctypes sử dụng mã kiểu
c_double[2. 4]
RawValue[c_double, 2. 4]
RawValue['d', 2. 4]
Cấu trúc của tôi[4, 6]
RawValue[MyStruct, 4, 6]
[c_short * 7][]
RawArray[c_short, 7]
RawArray['h', 7]
[c_int * 3][9, 2, 8]
RawArray[c_int, [9, 2, 8]]
RawArray['i', [9, 2, 8]]
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[]2
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[]3
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
đa xử lý. Người quản lý[]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 đa xử lý. quản lý. Trình quản lý cơ sở[địa chỉ=Không có . 0, authkey=None, serializer='pickle', ctx=None, *, shutdown_timeout=1.0]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__': mp.set_start_method['spawn'] q = mp.Queue[] p = mp.Process[target=foo, args=[q,]] p.start[] print[q.get[]] p.join[]66 để đả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]33 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]33 thì
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 được sử dụng. Nếu không thì authkey được sử dụng và nó phải là một chuỗi byte
bộ nối tiếp phải là
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 [sử dụng số sê-ri hóa] 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[]72 [sử dụng số sê-ri hóa]
ctx là một đối tượng bối cảnh, hoặc
[1, 4, 9]33 [sử dụng bối cảnh hiện tại]. Xem hàm
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[]5
shutdown_timeout là thời gian chờ tính bằng giây được sử dụng để đợi cho đến khi quá trình được người quản lý sử dụng hoàn tất trong phương thức. Nếu hết thời gian tắt máy, quá trình kết thúc. Nếu kết thúc quá trình cũng hết thời gian, quá trình bị hủy
Đã thay đổi trong phiên bản 3. 11. Đã thêm thông số shutdown_timeout.
start[[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]33 thì quy trình con sẽ 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[]78 khi nó bắt đầuget_server[]
Trả về một đối tượng
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 đại diện cho máy chủ thực dưới sự kiểm soát của Người quản lý. Đối tượng
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 hỗ trợ 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[]81
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__': mp.set_start_method['spawn'] q = mp.Queue[] p = mp.Process[target=foo, args=[q,]] p.start[] print[q.get[]] p.join[]79 còn có một thuộc tínhkết nối[]
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[]5tắt[]
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
đăng ký[typeid[ , callable[, 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]40 thì điều này có thể được để lại là
[1, 4, 9]33
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]33 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]33 thì
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[]92 được sử dụng thay thế 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__': mp.set_start_method['spawn'] q = mp.Queue[] p = mp.Process[target=foo, args=[q,]] p.start[] print[q.get[]] p.join[]94. ]
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]33 thì
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[]96 đượ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]33 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]39
các phiên bản cũng có một thuộc tính chỉ đọc
Địa chỉĐị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. bắt đầu quá trình máy chủ [nếu nó chưa bắt đầu] và sau đó trả về đối tượng người quản lý. 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 đa xử lý. quản lý. Trình quản lý đồng bộ hóaMộ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
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ẻ
Rào cản[các bên[ , action[, 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
BoundedSemaphore[[giá trị]]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
Điều kiện[[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.
Sự kiện[]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
Khóa[]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
Không gian tên[]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
Hàng đợi[[kích thước tối đa]]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
RLock[]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
Semaphore[[giá trị]]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
Array[typecode , sequence]Tạo một mảng và trả về một proxy cho nó
Value[typecode , value]Create an object with a writable
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[]44 attribute and return a proxy for itdict[]dict[mapping]dict[sequence]
Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
list[]list[sequence]Tạo một đối tượng được chia sẻ và trả lại proxy cho nó
Changed in version 3. 6. Shared objects are capable of being nested. For example, a shared container object such as a shared list can contain other shared objects which will all be managed and synchronized by the .
class multiprocessing. managers. NamespaceA type that can register with
A namespace object has no public methods, but does have writable attributes. Its representation shows the values of its attributes
However, when using a proxy for a namespace object, an attribute beginning with
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[]94 will be an attribute of the proxy and not an attribute of the referent
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]6
Customized managers
To create one’s own manager, one creates a subclass of and uses the classmethod to register new types or callables with the manager class. For example
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]7
Using a remote manager
It is possible to run a manager server on one machine and have clients use it from other machines [assuming that the firewalls involved allow it]
Chạy các lệnh sau sẽ tạo một máy chủ cho một hàng đợi được chia sẻ duy nhất 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[]8
One client can access the server as follows
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]9
Another client can also use it
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
Local processes can also access that queue, using the code from above on the client to access it remotely
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
Proxy Objects
A proxy is an object which refers to a shared object which lives [presumably] in a different process. The shared object is said to be the referent of the proxy. Multiple proxy objects may have the same referent
A proxy object has methods which invoke corresponding methods of its referent [although not every method of the referent will necessarily be available through the proxy]. In this way, a proxy can be used just like its referent can
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
Notice that applying to a proxy will return the representation of the referent, whereas applying will return the representation of the 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. As such, a referent can contain . This permits nesting of these managed lists, dicts, and other
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
Similarly, dict and list proxies may be nested inside one another
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
If standard [non-proxy] or objects are contained in a referent, modifications to those mutable values will not be propagated through the manager because the proxy has no way of knowing when the values contained within are modified. However, storing a value in a container proxy [which triggers 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[]30 on the proxy object] does propagate through the manager and so to effectively modify such an item, one could re-assign the modified value to the container proxy
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
This approach is perhaps less convenient than employing nested for most use cases but also demonstrates a level of control over the synchronization
Ghi chú
The proxy types in do nothing to support comparisons by value. So, for instance, we have
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
One should just use a copy of the referent instead when making comparisons
class multiprocessing. managers. BaseProxyProxy objects are instances of subclasses of
_callmethod[methodname[ , args[ , kwds]]]Call and return the result of a method of the proxy’s referent
If
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[]33 is a proxy whose referent is
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[]34 then the expression
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
will evaluate the expression
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
in the manager’s process
The returned value will be a copy of the result of the call or a proxy to a new shared object – see documentation for the method_to_typeid argument of
If an exception is raised by the call, then is re-raised by . If some other exception is raised in the manager’s process then this is converted into 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[]37 exception and is raised by
Note in particular that an exception will be raised if methodname has not been exposed
An example of the usage of
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_getvalue[]
Return a copy of the referent
If the referent is unpicklable then this will raise an exception
__repr__[]Return a representation of the proxy object
__str__[]Return the representation of the referent
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
Process Pools
One can create a pool of processes which will carry out tasks submitted to it with the class
class multiprocessing. pool. Pool[[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
processes is the number of worker processes to use. Nếu các quy trình là
[1, 4, 9]33 thì số được trả về bởi được sử dụng
Nếu bộ khởi tạo không phải là
[1, 4, 9]33 thì mỗi worker process sẽ 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[]78 khi nó bắt đầu
maxtasksperchild là số lượng tác vụ mà một worker process có thể hoàn thành trước khi nó thoát và được thay thế bằng một worker process mới, để cho phép giải phóng các tài nguyên không sử dụng. Maxtasksperchild mặc định là
[1, 4, 9]33, có nghĩa là worker process sẽ tồn tại miễn là pool
bối cảnh có thể được sử dụng để chỉ định bối cảnh được sử dụng để bắt đầu các quy trình worker. Thông thường, một nhóm được tạo bằng cách sử dụng hàm
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 hoặc phương thức của một đối tượng bối cảnh. Trong cả hai trường hợp bối cảnh được thiết lập một cách thích hợp
Lưu ý rằng các phương thức của đối tượng nhóm chỉ nên được gọi bởi quá trình tạo nhóm
Cảnh báo
objects have internal resources that need to be properly managed [like any other resource] by using the pool as a context manager or by calling and manually. Failure to do this can lead to the process hanging on finalization
Note that it is not correct to rely on the garbage collector to destroy the pool as CPython does not assure that the finalizer of the pool will be called [see for more information]
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
apply[func[ , args[ , kwds]]]Call func with arguments args and keyword arguments kwds. It blocks until the result is ready. Given this blocks, is better suited for performing work in parallel. Additionally, func is only executed in one of the workers of the pool
apply_async[func[ , args[ , kwds[ , callback[ , error_callback]]]]]A variant of the method which returns a 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
map[func , iterable[ , chunksize]]A parallel equivalent of the built-in function [it supports only one iterable argument though, for multiple iterables see ]. 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
Note that it may cause high memory usage for very long iterables. Consider using or with explicit chunksize option for better efficiency
map_async[func , iterable[ , chunksize[ , callback[ , error_callback]]]]A variant of the method which returns a 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
imap[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
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[]65
Also if chunksize is
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[]65 then the
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[]67 method of the iterator returned by the method has an optional timeout parameter.
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[]69 will raise if the result cannot be returned within timeout secondsimap_unordered[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”. ]
starmap[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
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[]73 results in
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
Mới trong phiên bản 3. 3
starmap_async[func , iterable[ , chunksize[ , callback[ , error_callback]]]]Một sự kết hợp của và lặp đi lặp lại trên iterable của iterables và gọi func với iterables được giải nén. Returns a result object
Mới trong phiên bản 3. 3
đóng[]Prevents any more tasks from being submitted to the pool. Once all the tasks have been completed the worker processes will exit
terminate[]Stops the worker processes immediately without completing outstanding work. When the pool object is garbage collected will be called immediately
tham gia[]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 multiprocessing. pool. AsyncResultThe class of the result returned by and
get[[timeout]]Return the result when it arrives. If timeout is not
[1, 4, 9]33 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 wait[[timeout]]
Wait until the result is available or until timeout seconds pass
ready[]Return whether the call has completed
successful[]Return whether the call completed without raising an exception. Will raise if the result is not ready
Changed in version 3. 7. If the result is not ready, is raised instead of .
The following example demonstrates the use of a pool
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
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
multiprocessing. connection. deliver_challenge[connection , authkey]Send a randomly generated message to the other end of the connection and wait for a reply
Nếu câu trả lời khớp với thông báo của tin nhắn sử dụng authkey làm khóa thì tin nhắn chào mừng sẽ được gửi đến đầu kia của kết nối. Nếu không thì được nâng lên
đa xử lý. sự liên quan. answer_challenge[kết nối , mã xác thực]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
multiprocessing. connection. Client[address[ , family[ , authkey]]]Attempt to set up a connection to the listener which is using address address, returning a
The type of the connection is determined by family argument, but this can generally be omitted since it can usually be inferred from the format of address. [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. is raised if authentication fails. See
class multiprocessing. connection. Listener[[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ú
If an address of ‘0. 0. 0. 0’ is used, the address will not be a connectable end point on Windows. If you require a connectable end-point, you should use ‘127. 0. 0. 1’
family is the type of socket [or named pipe] to use. This can be one of the strings
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 [for a TCP socket],
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[]01 [for a Unix domain socket] or
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[]02 [for a Windows named pipe]. Of these only the first is guaranteed to be available. If family is
[1, 4, 9]33 then the family is inferred from the format of address. If address is also
[1, 4, 9]33 then a default is chosen. This default is the family which is assumed to be the fastest available. See . Note that if family 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[]01 and address is
[1, 4, 9]33 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. is raised if authentication fails. See
accept[]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
đóng[]Close the bound socket or named pipe of the listener object. This is called automatically when the listener is garbage collected. However it is advisable to call it explicitly
Listener objects have the following read-only properties
Địa chỉThe address which is being used by the Listener object
last_acceptedThe address from which the last accepted connection came. If this is unavailable then it is
[1, 4, 9]33
New in version 3. 3. Listener objects now support the context management protocol – see . returns the listener object, and calls .
multiprocessing. connection. wait[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]33 then it will block for an unlimited period. Thời gian chờ âm tương đương với thời gian chờ bằng 0
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, 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[]21 almost equivalent
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[]22. The difference is that, if is interrupted by a signal, it can raise with an error number 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[]25, 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, 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[]27] or it can be an object with 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[]28 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, 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 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[]1
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[]2
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[]3
Address Formats
An
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 address is a tuple of the formfrom 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[]
32 where hostname is a string and port is an integerAn
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[]
01 address is a string representing a filename on the filesystemAn
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[]
02 address is a string of the formfrom 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. To use to connect to a named pipe on a remote computer called ServerName one should use an address of the formfrom 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[]
37 instead
Note that any string beginning with two backslashes is assumed by default to be an
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[]02 address rather than an
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[]01 address
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__': mp.set_start_method['spawn'] q = mp.Queue[] p = mp.Process[target=foo, args=[q,]] p.start[] print[q.get[]] p.join[]69 is used [see ]. This value will be automatically inherited by any object that the current process creates. Điều này có nghĩa là [theo mặc định] tất cả các quy trình của chương trình đa quy trình sẽ chia sẻ một khóa xác thực duy nhất có thể được sử dụng khi thiết lập kết nối giữa chúng
Các khóa xác thực phù hợp cũng có thể được tạo bằng cách sử dụng
Logging
Một số hỗ trợ cho ghi nhật ký có sẵn. 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
đa xử lý. get_logger[]Returns the logger used by . If necessary, a new one will be created
When first created the logger has level
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[]50 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
multiprocessing. log_to_stderr[level=None]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, 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. You can modify
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[]54 of the logger by passing 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[]55 argument
Dưới đây là phiên ví dụ có bật ghi nhật ký
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
For a full table of logging levels, see the module
mô-đun
replicates the API of but is no more than a wrapper around the module
In particular, 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[]5 function provided by returns an instance of , which is a subclass of that supports all the same method calls but uses a pool of worker threads rather than worker processesclass multiprocessing. pool. ThreadPool[[processes[ , initializer[ , initargs]]]]
A thread pool object which controls a pool of worker threads to which jobs can be submitted. instances are fully interface compatible with instances, and their resources must also be properly managed, either by using the pool as a context manager or by calling and manually
processes is the number of worker threads to use. If processes is
[1, 4, 9]33 then the number returned by is used
Nếu bộ khởi tạo không phải là
[1, 4, 9]33 thì mỗi worker process sẽ 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[]78 khi nó bắt đầu
Unlike , maxtasksperchild and context cannot be provided
Ghi chú
A shares the same interface as , which is designed around a pool of processes and predates the introduction of the module. As such, it inherits some operations that don’t make sense for a pool backed by threads, and it has its own type for representing the status of asynchronous jobs, , that is not understood by any other libraries
Users should generally prefer to use , which has a simpler interface that was designed around threads from the start, and which returns instances that are compatible with many other libraries, including
Programming guidelines
There are certain guidelines and idioms which should be adhered to when using
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. ]
Điều này có nghĩa là bất cứ khi nào bạn sử dụng hàng đợi, bạn cần đảm bảo rằng tất cả các mục đã được đưa vào hàng đợi cuối cùng sẽ bị xóa trước khi quy trình được tham gia. 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[]5A fix here would be to swap the last two lines [or simply remove 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[]88 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[]6should 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[]7
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[]8in 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[]91 method — this resulted in issues with processes-in-processes. This has been changed toimport 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[]9Which 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. This danger is that if multiple processes call on this file-like object, it could result in the same data being flushed to the object multiple times, resulting in corruption
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__': ctx = mp.get_context['spawn'] q = ctx.Queue[] p = ctx.Process[target=foo, args=[q,]] p.start[] print[q.get[]] p.join[]0For more information, see bpo-5155, bpo-5313 and bpo-5331
The spawn and forkserver start methods
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]43 are picklable. Also, if you subclass then make sure that instances will be picklable when the method is called
Global variables
Hãy nhớ rằng nếu mã chạy trong một tiến trình con cố gắng truy cập vào một biến toàn cục, thì giá trị mà nó thấy [nếu có] có thể không giống với giá trị trong tiến trình cha tại thời điểm được gọi
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[]1Instead one should protect the “entry point” of the program by using
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[]99 as followsimport 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[Có thể bỏ dòng
from multiprocessing import Process def f[name]: print['hello', name] if __name__ == '__main__': p = Process[target=f, args=['bob',]] p.start[] p.join[]88 nếu chương trình sẽ chạy bình thường thay vì đóng băng. ]Điều này cho phép trình thông dịch Python mới được tạo ra nhập mô-đun một cách an toàn và sau đó chạy hàm
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 của mô-đunSimilar restrictions apply if a pool or manager is created in the main module
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[]3
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[]4
An example showing how to use queues to feed tasks to a collection of worker processes and collect the results