Một thay thế gọn gàng, sạch sẽ cho xoắn của Python? [đóng cửa]


222

Một (lâu) trong khi trước đây tôi đã viết một mạng nhện mà tôi đã đa luồng để cho phép các yêu cầu đồng thời xảy ra cùng một lúc. Đó là thời trẻ Python của tôi, vào những ngày trước khi tôi biết về GIL và những tai ương liên quan mà nó tạo ra cho mã đa luồng (IE, hầu hết các công cụ thời gian chỉ kết thúc nối tiếp!) ...

Tôi muốn làm lại mã này để làm cho nó mạnh hơn và hoạt động tốt hơn. Về cơ bản có hai cách tôi có thể làm điều này: tôi có thể sử dụng mô-đun đa xử lý mới trong 2.6+ hoặc tôi có thể sử dụng mô hình dựa trên sự kiện / lò phản ứng. Tôi thà làm sau này vì nó đơn giản hơn và ít bị lỗi hơn.

Vì vậy, câu hỏi liên quan đến khuôn khổ nào sẽ phù hợp nhất với nhu cầu của tôi. Sau đây là danh sách các tùy chọn tôi biết cho đến nay:

  • Twisted : Các ông lớn của khung lò phản ứng Python: có vẻ phức tạp và hơi phình to. Dốc học đường cho một nhiệm vụ nhỏ.
  • Eventlet : Từ những kẻ ở lindenlab . Khung dựa trên Greenlet hướng đến các loại nhiệm vụ này. Tôi đã xem mã mặc dù và nó không quá đẹp: không tuân thủ pep8, rải rác với các bản in (tại sao mọi người làm điều này trong một khung!?), API có vẻ hơi không nhất quán.
  • PyEv : Chưa trưởng thành, dường như không có ai sử dụng nó ngay bây giờ mặc dù nó dựa trên sự hời hợt nên nó có một phần phụ trợ vững chắc.
  • asyncore : Từ stdlib: über cấp thấp, có vẻ như rất nhiều công việc liên quan chỉ để có được một cái gì đó lên khỏi mặt đất.
  • tornado : Mặc dù đây là một sản phẩm hướng máy chủ được thiết kế cho các trang web động của máy chủ nhưng nó có tính năng máy khách HTTP không đồng bộ và ioloop đơn giản . Có vẻ như nó có thể hoàn thành công việc nhưng không phải là những gì nó được dự định. [sửa: không may chạy trên Windows, điều này không phù hợp với tôi - đó là yêu cầu đối với tôi để hỗ trợ nền tảng khập khiễng này]

Có bất cứ điều gì tôi đã bỏ lỡ tất cả? Chắc chắn phải có một thư viện ngoài kia phù hợp với vị trí ngọt ngào của thư viện mạng không đồng bộ được đơn giản hóa!

[chỉnh sửa: lớn nhờ intgr cho con trỏ của mình đến trang này . Nếu bạn cuộn xuống phía dưới, bạn sẽ thấy có một danh sách các dự án thực sự tốt đẹp nhằm giải quyết nhiệm vụ này bằng cách này hay cách khác. Có vẻ như mọi thứ thực sự đã tiến lên kể từ khi bắt đầu Twisted: mọi người dường như ủng hộ một giải pháp dựa trên đồng quy hơn là một lò phản ứng / gọi lại theo định hướng truyền thống. Lợi ích của cách tiếp cận này là mã trực tiếp rõ ràng hơn: Tôi chắc chắn đã tìm thấy trong quá khứ, đặc biệt là khi làm việc với boost.asiotrong C ++, mã dựa trên gọi lại có thể dẫn đến các thiết kế có thể khó theo dõi và tương đối khó hiểu đối với mắt không được đào tạo. Sử dụng đồng quy cho phép bạn viết mã trông ít đồng bộ hơn một chút. Tôi đoán bây giờ nhiệm vụ của tôi là tìm ra một trong những thư viện mà tôi thích giao diện này và cho nó đi! Vui mừng tôi đã hỏi bây giờ ...]

[sửa: có lẽ quan tâm đến bất kỳ ai theo dõi hoặc vấp phải câu hỏi này hoặc quan tâm đến chủ đề này theo bất kỳ ý nghĩa nào: Tôi đã tìm thấy một bài viết thực sự tuyệt vời về tình trạng hiện tại của các công cụ có sẵn cho công việc này]


14
Python đa luồng, nó không cho phép hai luồng chạy mã Python đồng thời.
intgr

86
Tôi đã học được nhiều hơn từ câu hỏi của bạn hơn là từ câu trả lời cho nó.
Denis Otkidach

2
@Denis: heh, cảm ơn tôi đoán vậy! Cũng có một số gợi ý hay trong các câu trả lời, cụ thể là intgr. Tôi biết về rất nhiều lựa chọn ngoài kia và tôi không chỉ muốn câu trả lời được đóng gói với những câu hỏi đó nên tôi nghĩ tôi sẽ gặp rắc rối khi đánh vần những gì tôi biết :)
jkp

5
> bây giờ mọi người dường như ủng hộ một giải pháp dựa trên đồng quy hơn là một lò phản ứng / gọi lại theo định hướng truyền thống Đây không phải là một so sánh hợp lý. Các giải pháp "đồng quy dựa trên thường xuyên" và "hướng lò phản ứng" là trực giao. .
Jean-Paul Calderone

2
Một vài điểm cần thêm: 1. Tornado chạy rất tốt trên Windows. Nó không phải là hiệu suất và khả năng mở rộng vì nó sử dụng selectcho ghép kênh I / O. Nhưng bạn sẽ có thể có được một hiệu suất tốt từ nó với tornado-pyuv . 2. Hiện nay, asyncio bằng Python 3.3+ và backport nó trollius cho phép để chạy bất kỳ ứng dụng Tornado trong vòng lặp sự kiện của nó (Twisted sẽ được hỗ trợ sớm).
schlamar

Câu trả lời:


28

Tôi thích mô-đun Python đồng thời dựa trên microthreads Stackless hoặc Greenlets để phân luồng nhẹ. Tất cả các I / O mạng chặn được thực hiện không đồng bộ trong một libeventvòng lặp, do đó, nó sẽ có hiệu quả gần như một máy chủ không đồng bộ thực sự.

Tôi cho rằng nó tương tự như Eventlet theo cách này.

Nhược điểm là API của nó khá khác so với sockets/ threadingmô-đun của Python ; bạn cần viết lại một chút công bằng của ứng dụng của bạn (hoặc viết một lớp shim tương thích)

Chỉnh sửa: Có vẻ như cũng có cogen , tương tự, nhưng sử dụng các trình tạo nâng cao của Python 2.5 cho các coroutines của nó, thay vì Greenlets. Điều này làm cho nó di động hơn đồng thời và các lựa chọn thay thế khác. Mạng I / O được thực hiện trực tiếp với epoll / kqueue / iocp.


@intgr: liên kết tuyệt vời. Tôi đã từng nhìn thấy cả hai thứ đó trước đây, đó là những thứ mà tôi hy vọng sẽ thấy tuôn ra. +1
jkp

3
Có vẻ như sự đồng tình là một dự án chết với việc họ là bản cập nhật cuối cùng bốn năm trước.
Gewthen

Dự án đã chết, Hyves cũng vậy!
Bahadir Cambel

1
Rất nhiều điều đã xảy ra kể từ Python 2.5. asyncio trong Python 3.5 là tuyệt vời.
Joseph Sheedy

99

Twisted là phức tạp, bạn đúng về điều đó. Xoắn không phồng lên.

Nếu bạn xem tại đây: http://twistedmatrix.com/trac/browser/trunk/twisted bạn sẽ tìm thấy một bộ có tổ chức, toàn diện và được kiểm tra rất tốt về nhiều giao thức của internet, cũng như mã trợ giúp để viết và triển khai các ứng dụng mạng rất tinh vi. Tôi sẽ không nhầm lẫn sự phình to với tính toàn diện.

Mọi người đều biết rằng tài liệu Twisted không thân thiện với người dùng nhất từ ​​cái nhìn đầu tiên và tôi tin rằng điều này làm mất đi một số lượng người không may. Nhưng Twisted là tuyệt vời (IMHO) nếu bạn đặt thời gian. Tôi đã làm và nó đã được chứng minh là xứng đáng, và tôi khuyên người khác nên thử như vậy.


4
@clemesha: có thể bạn đúng, và nó không bị tải, nhưng có vẻ như có quá nhiều thứ để tôi phải làm một cái gì đó đơn giản. Tôi hiểu lập trình async, tôi đã làm việc trong C ++ với boost :: asio vì vậy các khái niệm không phải là mới, nhưng tất cả các kẹo cao su phù hợp với việc thực hiện các công cụ xoắn: đó là một thế giới hoàn toàn mới, giống như django dành cho công cụ web. Một lần nữa khi tôi đang làm công cụ web, tôi làm việc với mã WSGI nhẹ và chỉ kết nối những gì tôi cần. Tôi đoán ngựa cho các khóa học.
jkp

7
@clemesha: erm, hôm nay tôi đã lao vào để có một cái nhìn: xoắn có trọng lượng 20MB! Ngay cả lõi là 12 MB .... nếu đó không phải là cồng kềnh, tôi không chắc chắn đó là gì.
jkp

29
Các API xoắn cơ bản là khá nhỏ (lò phản ứng, hoãn lại, giao thức). Hầu hết các mã Twisted là các triển khai giao thức không đồng bộ bằng cách sử dụng các điều cơ bản đó. "Bloat" không phải là một tính từ hữu ích ở đây (hoặc thực sự trong hầu hết các trường hợp). Kích thước xoắn là hợp lý cho số lượng công cụ nó làm.
daf

56

geventeventlet được dọn sạch .

API-khôn ngoan, nó tuân theo các quy ước tương tự như thư viện tiêu chuẩn (cụ thể là các mô-đun luồng và đa xử lý), nơi nó có ý nghĩa. Vì vậy, bạn có những thứ quen thuộc như QueueEvent để làm việc.

Nó chỉ hỗ trợ libevent ( update: libev kể từ 1.0 ) khi triển khai lò phản ứng nhưng tận dụng tối đa lợi thế của nó, có máy chủ WSGI nhanh dựa trên libevent-http và giải quyết các truy vấn DNS thông qua libevent-dns thay vì sử dụng nhóm luồng như hầu hết các thư viện khác làm ( cập nhật: vì 1.0 c-ares được sử dụng để thực hiện các truy vấn DNS không đồng bộ; threadpool cũng là một tùy chọn.)

Giống như eventlet, nó làm cho các cuộc gọi lại và Trì hoãn không cần thiết bằng cách sử dụng greenlets .

Kiểm tra các ví dụ: tải xuống đồng thời nhiều url , webchat bỏ phiếu dài .


4
Tôi sẽ tham gia lần thứ hai - Sau khi xem xét nhiều giải pháp, gevent đã làm việc rất tốt cho tôi. Nó cho phép tôi giữ lại phần tốt hơn của chương trình hiện tại của mình và những thay đổi bắt buộc là không đáng kể - Tốt nhất là, nếu mã cần được duy trì trong 3, 4, 5, ... năm, nó vẫn thực hiện Đối với bất kỳ ai không quen thuộc với gevent, showstopper lớn nhất cho Twisted là đường cong học tập mạnh mẽ, điều này gây ra vấn đề không chỉ khi thực hiện, mà còn xuống dòng trong quá trình bảo trì ...
Martin Tournoij

27

Một so sánh thực sự thú vị về các khung như vậy đã được Nicholas Piël tổng hợp trên blog của mình: nó rất đáng để đọc!


2
Mặc dù tôi đồng ý rằng bài viết đó là một bài đọc thú vị, tôi nghĩ rằng đáng để xem xét tính hợp lệ của các điểm chuẩn được trình bày. Xem các bình luận tại đây: reddit.com/r/programming/comments/ahepg/
Kẻ

1
@clemesha, trong khi điểm đáng chú ý trong trang reddit đó, điểm chuẩn được thực hiện trên máy lõi kép và có khả năng không bị lỗ hổng nghiêm trọng được mô tả. Tôi cho rằng có thể cả máy khách và máy chủ đều chạy trên cùng một lõi, nhưng dường như không có khả năng.
Peter Hansen

15

Không có giải pháp nào trong số này sẽ tránh được thực tế rằng GIL ngăn chặn sự song song của CPU - chúng chỉ là những cách tốt hơn để có được sự song song IO mà bạn đã có với các luồng. Nếu bạn nghĩ rằng bạn có thể làm IO tốt hơn, bằng mọi cách hãy theo đuổi một trong những điều này, nhưng nếu nút cổ chai của bạn đang xử lý thì kết quả sẽ không có gì giúp được ngoại trừ mô đun đa xử lý.


Có gì sai khi sử dụng nhiều quy trình?
Emil Ivanov

3
Không có gì cả, do đó đề nghị sử dụng mô-đun đa xử lý.
Adam Hupp

11

Tôi sẽ không đi xa đến mức gọi Twisted cồng kềnh, nhưng rất khó để quấn đầu bạn. Tôi đã tránh thực sự ổn định trong một thời gian học vì tôi luôn muốn một cái gì đó dễ dàng hơn một chút cho 'các nhiệm vụ nhỏ'.

Tuy nhiên, bây giờ tôi đã làm việc với nó một số điều nữa tôi phải nói rằng có tất cả các pin đi kèm là RẤT đẹp.

Tất cả các thư viện không đồng bộ khác mà tôi đã làm việc cuối cùng đều kém trưởng thành hơn so với chúng thậm chí còn xuất hiện. Vòng lặp sự kiện của Twisted là rắn.

Tôi không chắc chắn làm thế nào để giải quyết đường cong học tập Twisted dốc. Nó có thể hữu ích nếu ai đó sẽ rẽ nhánh nó và dọn dẹp một vài thứ, như loại bỏ tất cả các hành trình tương thích ngược và các dự án đã chết. Nhưng đó là bản chất của phần mềm trưởng thành tôi đoán.


Nếu bạn đã từng tìm hiểu cách lò phản ứng gtk được triển khai trong Windows (bỏ phiếu khó khăn cứ sau 10ms: twistmatrix.com/trac/browser/trunk/twisted/iNET/ ,), bạn sẽ không gọi đó là "trưởng thành" ...
schlamar

2
Xin chào @schlamar. Vụ hack khó chịu này đã được triển khai như một cách giải quyết cho một số lỗi khá nghiêm trọng trong GTK +, vào thời điểm đó khi có ít mối quan tâm hơn về hiệu quả sử dụng điện :). Nhưng, cái hay của Twisted là chúng ta có thể gặp lỗi này một lần , sửa nó trong khung và người dùng của chúng ta không cần phải lo lắng về nó. Bạn có muốn đóng góp một bản sửa lỗi giải quyết vấn đề này và loại bỏ (không dùng nữa và sau đó xóa) PortableGtkReactor?
Glyph

1
@Glyph Tôi đã thêm lời khuyên hữu ích về twistmatrix.com/trac/ticket/4744#comment:2 nếu người khác muốn giải quyết vấn đề này, vì một số vấn đề vẫn còn tồn tại. BTW, bạn có thể đã giải quyết vấn đề này hiệu quả hơn nhiều bằng cách lên lịch các cuộc gọi lại giữa hai vòng lặp sự kiện.
schlamar

7

Kamaelia chưa được đề cập đến. Mô hình đồng thời của nó dựa trên việc kết nối các thành phần với nhau bằng thông điệp truyền giữa hộp thư đến và hộp thư đi. Đây là một tổng quan ngắn gọn.


5
Tôi đã sử dụng kamaelia cho một ứng dụng - nó vô cùng đau đớn. IMHO có những lựa chọn khác, tốt hơn cho concurrenct trong python (hầu hết được đề cập ở trên)
Ben Ford

7

Tôi đã bắt đầu sử dụng xoắn cho một số thứ. Vẻ đẹp của nó gần như là vì nó "bồng bềnh". Có các kết nối cho bất kỳ giao thức chính nào ngoài đó. Bạn có thể có một bot jabber sẽ nhận lệnh và đăng lên máy chủ irc, gửi email cho ai đó, chạy lệnh, đọc từ máy chủ NNTP và theo dõi trang web để thay đổi. Tin xấu là nó có thể làm tất cả những điều đó và có thể khiến mọi thứ trở nên quá phức tạp đối với các nhiệm vụ đơn giản như OP giải thích. Ưu điểm của python là bạn chỉ bao gồm những gì bạn cần. Vì vậy, trong khi tải xuống có thể là 20mb, bạn chỉ có thể bao gồm 2mb thư viện (vẫn còn rất nhiều). Khiếu nại lớn nhất của tôi với xoắn là mặc dù chúng bao gồm các ví dụ, bất cứ điều gì ngoài máy chủ tcp cơ bản là của riêng bạn.

Mặc dù không phải là một giải pháp python, tôi đã thấy node.js có được lực kéo nhiều hơn vào cuối. Trong thực tế, tôi đã xem xét xem xét nó cho các dự án nhỏ hơn nhưng tôi chỉ co rúm lại khi nghe javascript :)


Tôi là một fan hâm mộ Python lớn. - Kiểm tra Javascript Javascript - Các bộ phận tốt từ Douglas Crockford (3, 4 video). Và nhìn trộm CoffeeScript. Hóa ra JS có những thứ Python nên có, ngoại trừ Cú pháp, haha. CS đã cố gắng giảm thiểu điều đó, nhưng hơi vụng về về điều đó ...
Robert Siemer

4

Có một cuốn sách hay về chủ đề: "Những điều cốt yếu về lập trình mạng xoắn", của Abe Fettig. Các ví dụ cho thấy cách viết mã Pythonic và với cá nhân tôi, đừng đánh tôi như vậy dựa trên khung cồng kềnh. Nhìn vào các giải pháp trong cuốn sách, nếu chúng không sạch, thì tôi không biết sạch nghĩa là gì.

Sự đố kị duy nhất của tôi là giống như tôi có với các khung khác, như Ruby. Tôi lo lắng, nó có mở rộng quy mô không? Tôi ghét phải cam kết một khách hàng với một khuôn khổ sẽ có vấn đề về khả năng mở rộng.


4

Whizzer là một khung ổ cắm không đồng bộ nhỏ sử dụng pyev. Nó rất nhanh, chủ yếu là vì pyev. Nó cố gắng cung cấp một giao diện tương tự như xoắn với một số thay đổi nhỏ.


2

Cũng thử Syncless . Nó dựa trên coroutine (vì vậy nó tương tự như Concurrence, Eventlet và gevent). Nó thực hiện các thay thế không chặn trong drop-in cho socket.socket, socket.gethostbyname (v.v.), ssl.SSLSocket, time.s ngủ và select.select. Thật nhanh. Nó cần Stackless Python và libevent. Nó chứa một phần mở rộng Python bắt buộc được viết bằng C (Pyrex / Cython).


2

Tôi xác nhận sự tốt đẹp của không đồng bộ . Nó có thể sử dụng libev (phiên bản mới hơn, sạch hơn và hiệu suất tốt hơn của libevent). Đôi khi, nó không có nhiều sự hỗ trợ như những người có khả năng, nhưng bây giờ quá trình phát triển tiến xa hơn và rất hữu ích.


1

Nếu bạn chỉ muốn một Thư viện yêu cầu HTTP đơn giản, gọn nhẹ thì tôi thấy Unirest thực sự tốt


0

Bạn được chào đón để xem PyWorks, một cách tiếp cận khá khác biệt. Nó cho phép các cá thể đối tượng chạy trong luồng riêng của chúng và thực hiện chức năng gọi hàm đến đối tượng đó không đồng bộ.

Chỉ cần để một lớp kế thừa từ Nhiệm vụ thay vì đối tượng và nó không đồng bộ, tất cả các cuộc gọi phương thức là Proxy. Giá trị trả về (nếu bạn cần chúng) là các proxy tương lai.

res = obj.method( args )
# code continues here without waiting for method to finish
do_something_else( )
print "Result = %d" % res # Code will block here, if res not calculated yet

PyWorks có thể được tìm thấy trên http://bitbucket.org/raindog/pyworks


1
Mặc dù điều này rất thú vị và có thể phù hợp với một số tác vụ, nhưng việc sử dụng các luồng để kết nối mạng hoạt động kém (đặc biệt là trên Python do GIL). Và đây chính xác là câu hỏi: một khung sự kiện hoặc với đa xử lý. Vì vậy, câu trả lời của bạn rõ ràng nằm ngoài phạm vi ...
schlamar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.