concurrent.interpreters --- Nhiều trình thông dịch trong cùng một quy trình¶
Added in version 3.14.
Source code: Lib/concurrent/interpreters
Mô-đun concurrent.interpreters xây dựng các giao diện cấp cao hơn trên mô-đun _interpreters cấp thấp hơn.
Mô-đun này chủ yếu nhằm cung cấp một API cơ bản để quản lý các trình thông dịch (AKA "trình thông dịch phụ") và chạy mọi thứ trong đó. Việc chạy chủ yếu liên quan đến việc chuyển sang trình thông dịch (trong luồng hiện tại) và gọi một hàm trong ngữ cảnh thực thi đó.
Đối với tính đồng thời, bản thân các trình thông dịch (và mô-đun này) không cung cấp nhiều thứ hơn ngoài sự cô lập, bản thân điều này không hữu ích. Tính đồng thời thực tế có sẵn riêng biệt thông qua threads Xem below
Xem thêm
InterpreterPoolExecutorKết hợp các chủ đề với trình thông dịch trong một giao diện quen thuộc.
- Cách ly các mô-đun mở rộng
Cách cập nhật mô-đun mở rộng để hỗ trợ nhiều trình thông dịch.
sẵn có: not WASI.
Mô-đun này không hoạt động hoặc không có trên WebAssembly. Xem Nền tảng WebAssugging để biết thêm thông tin.
Chi tiết chính¶
Trước khi chúng ta đi sâu hơn, có một số chi tiết cần lưu ý về việc sử dụng nhiều trình thông dịch:
isolated, theo mặc định
không có chủ đề ngầm
không phải tất cả các gói PyPI đều hỗ trợ sử dụng trong nhiều trình thông dịch
Giới thiệu¶
Một "trình thông dịch" thực sự là bối cảnh thực thi của thời gian chạy Python. Nó chứa tất cả trạng thái mà thời gian chạy cần để thực thi một chương trình. Điều này bao gồm những thứ như trạng thái nhập và nội dung. (Mỗi luồng, ngay cả khi chỉ có luồng chính, có một số trạng thái thời gian chạy bổ sung, ngoài trình thông dịch hiện tại, liên quan đến ngoại lệ hiện tại và vòng lặp eval mã byte.)
Khái niệm và chức năng của trình thông dịch đã là một phần của Python kể từ phiên bản 2.2, nhưng tính năng này chỉ có trên C-API và chưa được nhiều người biết đến, còn isolation thì tương đối chưa hoàn thiện cho đến phiên bản 3.12.
Nhiều thông dịch viên và cách ly¶
Việc triển khai Python có thể hỗ trợ sử dụng nhiều trình thông dịch trong cùng một quy trình. CPython có hỗ trợ này. Mỗi trình thông dịch được cách ly một cách hiệu quả với những trình thông dịch khác (với một số lượng hạn chế các trường hợp ngoại lệ toàn bộ quy trình được quản lý cẩn thận đối với quy tắc).
Sự cô lập đó chủ yếu hữu ích như một sự tách biệt mạnh mẽ giữa các thành phần logic riêng biệt của một chương trình, nơi bạn muốn kiểm soát cẩn thận cách các thành phần đó tương tác.
Ghi chú
Về mặt kỹ thuật, các trình thông dịch trong cùng một quy trình không bao giờ có thể bị tách biệt hoàn toàn với nhau vì có rất ít hạn chế về quyền truy cập bộ nhớ trong cùng một quy trình. Thời gian chạy Python nỗ lực hết sức để tách biệt nhưng các mô-đun mở rộng có thể dễ dàng vi phạm điều đó. Do đó, không sử dụng nhiều trình thông dịch trong các tình huống nhạy cảm về bảo mật khi chúng không có quyền truy cập vào dữ liệu của nhau.
Chạy trong một thông dịch viên¶
Chạy trong một trình thông dịch khác liên quan đến việc chuyển sang trình thông dịch đó trong luồng hiện tại và sau đó gọi một số hàm. Thời gian chạy sẽ thực thi hàm bằng trạng thái của trình thông dịch hiện tại. Mô-đun concurrent.interpreters cung cấp API cơ bản để tạo và quản lý trình thông dịch cũng như thao tác chuyển đổi và gọi.
Không có chủ đề nào khác được tự động bắt đầu cho hoạt động. Tuy nhiên, có a helper cho điều đó. Có một trình trợ giúp chuyên dụng khác để gọi exec() dựng sẵn trong trình thông dịch.
Khi exec() (hoặc eval()) được gọi trong trình thông dịch, chúng sẽ chạy bằng mô-đun __main__ của trình thông dịch làm không gian tên "toàn cục". Điều này cũng đúng với các hàm không liên kết với bất kỳ mô-đun nào. Điều này giống như cách các tập lệnh được gọi từ dòng lệnh chạy trong mô-đun __main__.
Đồng thời và song song¶
Như đã lưu ý trước đó, trình thông dịch không tự cung cấp bất kỳ sự tương tranh nào. Chúng thể hiện rõ ràng bối cảnh thực thi biệt lập mà thời gian chạy sẽ sử dụng in the current thread. Sự tách biệt đó làm cho chúng giống với các quy trình, nhưng chúng vẫn đạt được hiệu quả trong quá trình, giống như các luồng.
Tất cả những gì đã nói, các thông dịch viên đương nhiên ủng hộ một số loại đồng thời nhất định. Có một tác dụng phụ mạnh mẽ của sự cô lập đó. Nó cho phép một cách tiếp cận đồng thời khác với cách bạn có thể thực hiện với async hoặc thread. Đó là một mô hình tương tranh tương tự như CSP hoặc mô hình diễn viên, một mô hình tương đối dễ hiểu.
Bạn có thể tận dụng mô hình đồng thời đó trong một luồng duy nhất, chuyển đổi qua lại giữa các trình thông dịch, kiểu Stackless. Tuy nhiên, mô hình này hữu ích hơn khi bạn kết hợp trình thông dịch với nhiều luồng. Điều này chủ yếu liên quan đến việc bắt đầu một chuỗi mới, nơi bạn chuyển sang một trình thông dịch khác và chạy những gì bạn muốn ở đó.
Mỗi luồng thực tế trong Python, ngay cả khi bạn chỉ chạy trong luồng chính, đều có ngữ cảnh thực thi current riêng. Nhiều luồng có thể sử dụng cùng một trình thông dịch hoặc các trình thông dịch khác nhau.
Ở cấp độ cao, bạn có thể coi sự kết hợp giữa các chuỗi và trình thông dịch là các chuỗi có tính năng chia sẻ tùy chọn.
Là một phần thưởng đáng kể, các trình thông dịch được cách ly đủ để chúng không chia sẻ GIL, điều đó có nghĩa là việc kết hợp các luồng với nhiều trình thông dịch sẽ cho phép thực hiện song song đa lõi hoàn toàn. (Điều này đã xảy ra kể từ Python 3.12.)
Giao tiếp giữa các phiên dịch viên¶
Trong thực tế, nhiều thông dịch viên chỉ hữu ích nếu chúng ta có cách giao tiếp giữa chúng. Điều này thường liên quan đến một số hình thức chuyển tin nhắn, nhưng thậm chí có thể có nghĩa là chia sẻ dữ liệu theo một cách được quản lý cẩn thận.
Với suy nghĩ này, mô-đun concurrent.interpreters cung cấp triển khai queue.Queue, có sẵn thông qua create_queue().
Tài liệu tham khảo¶
Mô-đun này xác định các chức năng sau:
- concurrent.interpreters.list_all()¶
Trả về một đối tượng
listcủaInterpreter, một đối tượng cho mỗi trình thông dịch hiện có.
- concurrent.interpreters.get_current()¶
Trả về đối tượng
Interpretercho trình thông dịch hiện đang chạy.
- concurrent.interpreters.get_main()¶
Trả về đối tượng
Interpretercho trình thông dịch chính. Đây là trình thông dịch thời gian chạy được tạo để chạy REPL hoặc tập lệnh được đưa ra ở dòng lệnh. Nó thường là duy nhất.
- concurrent.interpreters.create()¶
Khởi tạo trình thông dịch Python mới (không hoạt động) và trả về đối tượng
Interpretercho nó.
- concurrent.interpreters.create_queue()¶
Khởi tạo hàng đợi trình thông dịch chéo mới và trả về đối tượng
Queuecho nó.
Đối tượng phiên dịch¶
- class concurrent.interpreters.Interpreter(id)¶
Một thông dịch viên duy nhất trong quy trình hiện tại.
Nói chung,
Interpreterkhông nên được gọi trực tiếp. Thay vào đó, hãy sử dụngcreate()hoặc một trong các chức năng mô-đun khác.- id¶
(chỉ đọc)
ID của trình thông dịch cơ bản.
- whence¶
(chỉ đọc)
Một chuỗi mô tả nguồn gốc của trình thông dịch.
- is_running()¶
Trả về
Truenếu trình thông dịch hiện đang thực thi mã trong mô-đun__main__của nó vàFalsenếu ngược lại.
- close()¶
Hoàn thiện và tiêu diệt trình thông dịch.
- prepare_main(ns=None, **kwargs)¶
Liên kết các đối tượng trong mô-đun
__main__của trình thông dịch.Một số đối tượng thực sự được chia sẻ và một số đối tượng được sao chép một cách hiệu quả, nhưng hầu hết được sao chép qua
pickle. Xem Đối tượng “Chia sẻ”.
- exec(code, /, dedent=True)¶
Chạy mã nguồn đã cho trong trình thông dịch (trong luồng hiện tại).
- call(callable, /, *args, **kwargs)¶
Trả về kết quả của việc gọi hàm đã cho trong trình thông dịch (trong luồng hiện tại).
- call_in_thread(callable, /, *args, **kwargs)¶
Chạy hàm đã cho trong trình thông dịch (trong một chuỗi mới).
Ngoại lệ¶
- exception concurrent.interpreters.InterpreterError¶
Ngoại lệ này, một lớp con của
Exception, được đưa ra khi xảy ra lỗi liên quan đến trình thông dịch.
- exception concurrent.interpreters.InterpreterNotFoundError¶
Ngoại lệ này, một lớp con của
InterpreterError, được đưa ra khi trình thông dịch được nhắm mục tiêu không còn tồn tại.
- exception concurrent.interpreters.ExecutionFailed¶
Ngoại lệ này, một lớp con của
InterpreterError, được đưa ra khi mã đang chạy đưa ra một ngoại lệ chưa được phát hiện.- excinfo¶
Ảnh chụp nhanh cơ bản về ngoại lệ được đưa ra trong trình thông dịch khác.
Ngoại lệ này, một lớp con của
TypeError, được đưa ra khi một đối tượng không thể được gửi đến một trình thông dịch khác.
Giao tiếp giữa các phiên dịch viên¶
- class concurrent.interpreters.Queue(id)¶
Một trình bao bọc xung quanh hàng đợi có trình thông dịch chéo, cấp thấp, triển khai giao diện
queue.Queue. Hàng đợi cơ bản chỉ có thể được tạo thông quacreate_queue().Một số đối tượng thực sự được chia sẻ và một số đối tượng được sao chép một cách hiệu quả, nhưng hầu hết được sao chép qua
pickle. Xem Đối tượng “Chia sẻ”.- id¶
(chỉ đọc)
ID của hàng đợi.
- exception concurrent.interpreters.QueueEmptyError¶
Ngoại lệ này, một lớp con của
queue.Empty, được tạo ra từQueue.get()vàQueue.get_nowait()khi hàng đợi trống.
- exception concurrent.interpreters.QueueFullError¶
Ngoại lệ này, một lớp con của
queue.Full, được tạo ra từQueue.put()vàQueue.put_nowait()khi hàng đợi đầy.
Cách sử dụng cơ bản¶
Tạo trình thông dịch và chạy mã trong đó
từ các thông dịch viên nhập khẩu đồng thời
interp = thông dịch viên.create()
# Run trong chuỗi hệ điều hành hiện tại.
interp.exec('print("spam!")')
interp.exec("""if Đúng:
in('thư rác!')
""")
từ nhập khẩu văn bản
interp.exec(dedent("""
in('thư rác!')
"""))
chắc chắn chạy (arg):
trả lại đối số
res = interp.call(chạy, 'thư rác!')
in(res)
chắc chắn chạy():
in('thư rác!')
interp.call(chạy)
# Run trong chuỗi hệ điều hành mới.
t = interp.call_in_thread(chạy)
t.join()