2011-02-11 16 views
9

यहां कुछ कोड है जो मेरी समस्या का वर्णन करता है:पायथन - मैं इस कोड को एसिंक्रोनस कैसे बना सकता हूं?

def blocking1(): 
    while True: 
     yield 'first blocking function example' 

def blocking2(): 
    while True: 
     yield 'second blocking function example' 

for i in blocking1(): 
    print 'this will be shown' 

for i in blocking2(): 
    print 'this will not be shown' 

मेरे पास दो फ़ंक्शन हैं जिनमें while True loops शामिल हैं। इससे डेटा मिलेगा जो मैं फिर कहीं लॉग ऑन करूंगा (सबसे अधिक संभावना है, एक एसक्लाइट डेटाबेस में)।

मैं थ्रेडिंग के साथ खेल रहा हूं और इसे काम कर लिया है। हालांकि, मुझे वास्तव में यह पसंद नहीं है ... मैं जो करना चाहता हूं वह मेरे अवरुद्ध कार्यों को असीमित बना देता है। कुछ ऐसा है:

def blocking1(callback): 
    while True: 
     callback('first blocking function example') 

def blocking2(callback): 
    while True: 
     callback('second blocking function example') 

def log(data): 
    print data 

blocking1(log) 
blocking2(log) 

मैं इसे पायथन में कैसे प्राप्त कर सकता हूं? मैंने देखा है कि मानक पुस्तकालय एसिंककोर के साथ आता है और इस गेम में बड़ा नाम ट्विस्ट किया गया है लेकिन इनमें से दोनों सॉकेट आईओ के लिए उपयोग किए जाने लगते हैं।

मैं अपने गैर-सॉकेट से संबंधित, अवरुद्ध कार्यों को कैसे जोड़ सकता हूं?

+0

'क्या मैं करना चाहता हूं कि मेरे अवरुद्ध कार्यों को अतुल्यकालिक बनाएं 'इससे ​​कोई अर्थ नहीं आता है। आप या तो अपने फ़ंक्शन को ब्लॉक करना चाहते हैं, या आप इसे अतुल्यकालिक चाहते हैं। यदि आप इसे अतुल्यकालिक चाहते हैं, तो थ्रेड का उपयोग करें। मुझे नहीं पता कि समस्या क्या है। – Falmarri

+0

मैं चाहता हूं कि मेरे अवरुद्ध कार्य गैर-अवरुद्ध हो जाएं – dave

+0

ऐसे कई प्रश्न हैं जिनके बारे में उत्तर देने की आवश्यकता है कि उन कार्यों के निष्पादन को एक दूसरे के साथ नहीं, बल्कि आपके द्वारा चलाए जाने वाले सभी कोडों के साथ अंतःस्थापित किया जाता है। यह ऑपरेटिंग सिस्टम के लिए है, और आप आम तौर पर ऐसा कुछ क्यों थ्रेड का उपयोग करना चाहते हैं। क्या आप समझा सकते हैं कि आपको थ्रेडिंग के बारे में क्या पसंद नहीं है? यह ठीक तरह की समस्या है कि हल करने के लिए थ्रेडिंग बनाया गया था। –

उत्तर

1

यदि आप पूर्ण ओएस थ्रेडिंग का उपयोग नहीं करना चाहते हैं, तो आप Stackless का प्रयास कर सकते हैं, जो कि पाइथन का एक प्रकार है जो "माइक्रोथ्रेड" सहित कई रोचक विशेषताएं जोड़ता है। बहुत अच्छे examples हैं जो आपको उपयोगी लगेगा।

+0

दिलचस्प लगता है लेकिन मैं पाइथन – dave

+1

का उपयोग करने के लिए चिपकना पसंद करूंगा स्टैकलेस पायथन पाइथन है। – Falmarri

+0

मैंने परिचय टेक्स्ट का अर्थ दिया क्योंकि यह एक वैकल्पिक पायथन दुभाषिया है। मैं अब इसे और देख लूंगा। चीयर्स। – dave

9

आप सहकारी मल्टीटास्किंग के लिए जेनरेटर का उपयोग कर सकते हैं, लेकिन आपको अपना मुख्य लूप लिखना होगा जो उनके बीच नियंत्रण को पार कर लेता है।

यहाँ एक (बहुत सरल) उपरोक्त उदाहरण अपने उदाहरण का उपयोग करते हुए बताया गया है:

def blocking1(): 
    while True: 
     yield 'first blocking function example' 

def blocking2(): 
    while True: 
     yield 'second blocking function example' 


tasks = [blocking1(), blocking2()] 

# Repeat until all tasks have stopped 
while tasks: 
    # Iterate through all current tasks. Use 
    # tasks[:] to copy the list because we 
    # might mutate it. 
    for t in tasks[:]: 
     try: 
      print t.next() 
     except StopIteration: 
      # If the generator stops, remove it from the task list 
      tasks.remove(t) 

आप आगे नया जनरेटर है, जो तब कार्यों में जोड़ा जा सकता उपज के लिए जनरेटर की अनुमति देकर यह सुधार सकता है, लेकिन उम्मीद है कि इस सरल उदाहरण सामान्य विचार देंगे।

+0

यह एक अच्छा समाधान प्रतीत होता है। हालांकि, यदि दो जेनरेटर दो अलग-अलग इंटरफेस सुनने के लिए libpcap का उपयोग करना चाहते थे और पैकेट को स्नीफ किया था, तो क्या मैं किसी दिए गए समय पर लौटने वाले केवल एक जनरेटर के कारण पैकेट खो दूंगा? – dave

+0

@ माइक: हाँ। यदि आप पैकेट स्नीफिंग से संबंधित कुछ I/O करने जा रहे हैं, तो वास्तविक ट्रेडों का उपयोग करना एक बेहतर समाधान है (जब तक कि प्रश्न में I/O लाइब्रेरी मूल गैर-अवरुद्ध API प्रदान नहीं करती)। – shang

+1

असली जवाब यहां विनिर्देशों पर निर्भर करता है। यदि आप I/O कॉल अवरुद्ध कर रहे हैं और यह समस्या है, तो आपको * उन कॉल * को बदलने की आवश्यकता है ताकि वे अब अवरुद्ध न हों। आप अपने शेष कोड में कुछ भी नहीं कर सकते हैं ताकि इसे अतुल्यकालिक (धागे के बिना) बनाया जा सके जब तक कि आपके पास उन कार्यों का ईवेंट-संचालित संस्करण नहीं है। दूसरे शब्दों में, कीथ का जवाब देखें, और "मुड़ें का उपयोग करें"। – Glyph

2

घुमावदार ढांचा सिर्फ सॉकेट नहीं है। इसमें कई परिदृश्यों के लिए एसिंक्रोनस एडेप्टर हैं, जिनमें सबप्रोसेसेस के साथ बातचीत भी शामिल है। मैं उस पर एक नज़र डालने की सलाह देते हैं। यह वही करता है जो आप करने की कोशिश कर रहे हैं।

28

एक अवरुद्ध कार्य एक ऐसा फ़ंक्शन है जो वापस नहीं आता है, लेकिन फिर भी आपकी प्रक्रिया निष्क्रिय हो जाती है - अधिक काम पूरा करने में असमर्थ।

आप हमें अवरुद्ध करने वाले कार्यों को अवरुद्ध करने के लिए कह रहे हैं। हालांकि - जब तक आप एक ऑपरेटिंग सिस्टम नहीं लिख रहे हैं - आप में कोई अवरोधक कार्य नहीं है। आपके पास ऐसे कार्य हो सकते हैं जो ब्लॉक करते हैं क्योंकि वे सिस्टम कॉल को अवरुद्ध करने के लिए कॉल करते हैं, या आपके पास ऐसे कार्य हो सकते हैं जो "ब्लॉक" करते हैं क्योंकि वे बहुत अधिक गणना करते हैं।

अंतर्निहित सिस्टम कॉल गैर-अवरुद्ध किए बिना पूर्व प्रकार के फ़ंक्शन को गैर-अवरुद्ध करना असंभव है। उस सिस्टम कॉल के आधार पर, इसे आपके प्रोग्राम में इवेंट लूप जोड़ने के बिना इसे गैर-अवरुद्ध करना मुश्किल हो सकता है; आपको केवल कॉल करने की आवश्यकता नहीं है और इसे अवरुद्ध नहीं करना है, आपको यह निर्धारित करने के लिए एक और कॉल करना होगा कि उस कॉल का नतीजा कहीं भी वितरित किया जाएगा जहां आप इसे जोड़ सकते हैं।

इस प्रश्न का उत्तर एक बहुत लंबा पायथन कार्यक्रम है और विभिन्न ओएस इंटरफेस के कई स्पष्टीकरण और वे कैसे काम करते हैं, लेकिन सौभाग्य से मैंने पहले से ही एक अलग साइट पर जवाब लिखा है; मैंने इसे Twisted कहा। यदि आपका विशेष कार्य पहले से ही supported by a Twisted reactor है, तो आप भाग्य में हैं। अन्यथा, जब तक आपका कार्य कुछ मौजूदा ऑपरेटिंग सिस्टम अवधारणा को मैप करता है, तब तक आप इसका समर्थन करने के लिए एक रिएक्टर का विस्तार कर सकते हैं।व्यावहारिक रूप से बोलते हुए केवल इन तंत्रों में से 2 हैं: प्रत्येक समझदार ऑपरेटिंग सिस्टम पर फाइल डिस्क्रिप्टर, और विंडोज़ पर I/O प्राप्ति बंदरगाहों।

अन्य मामले में, यदि आपके कार्य बहुत सी CPU का उपभोग कर रहे हैं, और इसलिए वापस नहीं आ रहे हैं, तो वे वास्तव में अवरुद्ध नहीं हो रहे हैं; आपकी प्रक्रिया अभी भी साथ चल रही है और काम पूरा हो रही है। उस से निपटने के लिए तीन तरीके हैं:

  • अलग धागे
  • अलग प्रक्रियाओं
  • यदि आप कोई ईवेंट पाश है, एक काम है कि समय-समय पर पैदावार, लिखना इस तरह से कि यह करता है में काम लिख कर कुछ काम, फिर अन्य कार्यों को चलाने की अनुमति देने के लिए इवेंट लूप को निकट भविष्य में फिर से शुरू करने के लिए कहता है।

मुड़ में यह पिछले तकनीक विभिन्न तरीकों से पूरा किया जा सकता है, लेकिन यहां एक वाक्य रचना सुविधाजनक चाल यह आसान बनाता है:

from twisted.internet import reactor 
from twisted.internet.task import deferLater 
from twisted.internet.defer import inlineCallbacks, returnValue 

@inlineCallbacks 
def slowButSteady(): 
    result = SomeResult() 
    for something in somethingElse: 
     result.workHardForAMoment(something) 
     yield deferLater(reactor, 0, lambda : None) 
    returnValue(result) 
+2

ग्रेट पोस्ट। पिछले कुछ घंटों को नेट के चारों ओर खोज कर किसी अन्य पायथन सॉकेट अवरोधन मुद्दे पर जानकारी के लिए खर्च किया है और हालांकि यह पोस्ट एक अलग संदर्भ से संबंधित है (मेरा भूगर्भीय/ग्रीनलेट्स है), यह एक अच्छा शुरुआती अवलोकन है कि क्यों एक नियमित शुरुआत की स्थिति में अवरुद्ध हो सकता है अजगर। पोस्ट करने का शुक्रिया। – Matty

0

आपका कोड नहीं रोक रहा। blocking1() और यह भाई तुरंत इटरेटर्स लौटता है (अवरुद्ध नहीं), और न ही एक एकल पुनरावृत्ति ब्लॉक (आपके मामले में) करता है।

तुम दोनों iterators एक-एक करके से "खाने के लिए", अपने कार्यक्रम को खाने की कोशिश कर नहीं करना चाहते हैं "blocking1()" पूरी तरह से, इससे पहले जारी ...

for b1, b2 in zip(blocking1(), blocking2()): 
    print 'this will be shown', b1, 'and this, too', b2 
संबंधित मुद्दे