stop(); run_forever()
चाल क्योंकि stop
कैसे कार्यान्वित किया जाता है की काम करता है:
def stop(self):
"""Stop running the event loop.
Every callback scheduled before stop() is called will run.
Callback scheduled after stop() is called won't. However,
those callbacks will run if run() is called again later.
"""
self.call_soon(_raise_stop_error)
def _raise_stop_error(*args):
raise _StopError
तो, अगली बार घटना पाश रन और लंबित कॉलबैक कार्यान्वित करता है, यह _raise_stop_error
कॉल करने के लिए है, जो जन्म देती हो रहा है _StopError
। run_forever
पाश केवल कि विशिष्ट अपवाद पर टूट जाएगा:
def run_forever(self):
"""Run until stop() is called."""
if self._running:
raise RuntimeError('Event loop is running.')
self._running = True
try:
while True:
try:
self._run_once()
except _StopError:
break
finally:
self._running = False
तो, एक stop()
का समय निर्धारण और फिर बुला run_forever
द्वारा, आप अंत घटना पाश में से एक यात्रा चल रहा है, तो रोक एक बार यह _raise_stop_error
कॉलबैक हिट। आपने यह भी देखा होगा कि _run_once
को परिभाषित किया गया है और run_forever
द्वारा बुलाया गया है। आप इसे सीधे कॉल कर सकते हैं, लेकिन अगर कभी भी कॉलबैक चलाने के लिए तैयार नहीं होते हैं, तो यह कभी-कभी अवरुद्ध हो सकता है, जो वांछित नहीं हो सकता है। मुझे नहीं लगता कि वर्तमान में ऐसा करने का एक क्लीनर तरीका है - यह उत्तर एंड्रयू स्वेतलोव द्वारा प्रदान किया गया था, जो asyncio
योगदानकर्ता है; वह शायद बेहतर होगा कि कोई बेहतर विकल्प है या नहीं।:)
सामान्य तौर पर, अपने कोड, उचित लग रहा है, हालांकि मुझे लगता है कि आप इस run_once
दृष्टिकोण के साथ शुरू करने के लिए उपयोग नहीं करना चाहिए। यह निर्धारित करने योग्य नहीं है, अगर आप एक लंबी सूची या एक धीमी प्रणाली थी, यह सब कुछ मुद्रित करने के लिए दो से अधिक अतिरिक्त पुनरावृत्तियों पड़ सकता है। बजाय, आप बस खत्म करने के लिए एक प्रहरी कि रिसीवर बताता है बंद करने के लिए, और उसके बाद दोनों भेजें पर प्रतीक्षा करें और coroutines प्राप्त भेजना चाहिए:
import sys
import time
import socket
import asyncio
addr = ('127.0.0.1', 1064)
SENTINEL = b"_DONE_"
# ... (This stuff is the same)
@asyncio.coroutine
def sending(addr, dataiter):
loop = asyncio.get_event_loop()
for d in dataiter:
print("Sending:", d)
sock = socket.socket()
yield from send_close(loop, sock, addr, str(d).encode())
# Send a sentinel
sock = socket.socket()
yield from send_close(loop, sock, addr, SENTINEL)
@asyncio.coroutine
def receiving(addr):
loop = asyncio.get_event_loop()
sock = socket.socket()
try:
sock.setblocking(False)
sock.bind(addr)
sock.listen(5)
while True:
data = yield from accept_recv(loop, sock)
if data == SENTINEL: # Got a sentinel
return
print("Recevied:", data)
finally: sock.close()
def main():
loop = asyncio.get_event_loop()
# add these items to the event loop
recv = asyncio.async(receiving(addr), loop=loop)
send = asyncio.async(sending(addr, range(10)), loop=loop)
loop.run_until_complete(asyncio.wait([recv, send]))
main()
अंत में, asyncio.async
सही तरीके से घटना पाश करने के लिए कार्यों को जोड़ने के लिए है । create_task
अजगर 3.4.2 में जोड़ा गया है, ताकि आप किसी पुराने संस्करण है, तो यह अस्तित्व में नहीं होगा।
मुझे लगता है कि मैं वास्तव में समझ है कि यह कैसे पहली जगह में काम किया के लिए घटना पाश पर "कुल नियंत्रण" होने का विचार पसंद आया। मुझे लगता है कि समझ में आता है SENTINAL हालांकि, का उपयोग पसंद :) – vitiral