[PYTHON] 파이썬에서 비동기 메서드 호출?
PYTHON파이썬에서 비동기 메서드 호출?
파이썬에서 비동기 메서드 호출을위한 라이브러리가 있는지 궁금합니다. 네가 뭔가를 할 수 있다면 좋을거야.
@async
def longComputation():
<code>
token = longComputation()
token.registerCallback(callback_function)
# alternative, polling
while not token.finished():
doSomethingElse()
if token.finished():
result = token.result()
또는 비동기식이 아닌 루틴을 비동기식으로 호출 할 수 있습니다.
def longComputation()
<code>
token = asynccall(longComputation())
언어 핵심에서보다 세련된 전략을 원한다면 좋을 것입니다. 이것이 고려 되었습니까?
해결법
-
==============================
1.파이썬 2.6에서 추가 된 멀티 프로세싱 모듈을 사용할 수 있습니다. 프로세스 풀을 사용하고 다음과 같이 비동기 적으로 결과를 얻을 수 있습니다.
파이썬 2.6에서 추가 된 멀티 프로세싱 모듈을 사용할 수 있습니다. 프로세스 풀을 사용하고 다음과 같이 비동기 적으로 결과를 얻을 수 있습니다.
apply_async(func[, args[, kwds[, callback]]])
예 :
from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': pool = Pool(processes=1) # Start a worker processes. result = pool.apply_async(f, [10], callback) # Evaluate "f(10)" asynchronously calling callback when finished.
이것은 하나의 대안 일뿐입니다. 이 모듈은 원하는 것을 성취 할 수있는 많은 기능을 제공합니다. 또한 이것으로 데코레이터를 만드는 것이 정말 쉽습니다.
-
==============================
2.같은 것 :
같은 것 :
import threading thr = threading.Thread(target=foo, args=(), kwargs={}) thr.start() # Will run "foo" .... thr.is_alive() # Will return whether foo is running currently .... thr.join() # Will wait till "foo" is done
자세한 내용은 https://docs.python.org/2/library/threading.html#module-threading의 설명서를 참조하십시오. 이 코드는 Python 3에서도 작동해야합니다.
-
==============================
3.파이썬 3.5부터 비동기 함수를 위해 향상된 생성기를 사용할 수 있습니다.
파이썬 3.5부터 비동기 함수를 위해 향상된 생성기를 사용할 수 있습니다.
import asyncio import datetime
향상된 생성기 구문 :
@asyncio.coroutine def display_date(loop): end_time = loop.time() + 5.0 while True: print(datetime.datetime.now()) if (loop.time() + 1.0) >= end_time: break yield from asyncio.sleep(1) loop = asyncio.get_event_loop() # Blocking call which returns when the display_date() coroutine is done loop.run_until_complete(display_date(loop)) loop.close()
새로운 비동기 / 구문 대기 중 :
async def display_date(loop): end_time = loop.time() + 5.0 while True: print(datetime.datetime.now()) if (loop.time() + 1.0) >= end_time: break await asyncio.sleep(1) loop = asyncio.get_event_loop() # Blocking call which returns when the display_date() coroutine is done loop.run_until_complete(display_date(loop)) loop.close()
-
==============================
4.그것은 언어 중심이 아니지만, 당신이 원하는 것을하는 매우 성숙한 라이브러리는 Twisted입니다. 콜백 또는 오류 처리기 ( "errbacks")를 연결할 수있는 Deferred 개체를 소개합니다. Deferred는 기본적으로 함수가 결국 결과를 가져 오는 "약속"입니다.
그것은 언어 중심이 아니지만, 당신이 원하는 것을하는 매우 성숙한 라이브러리는 Twisted입니다. 콜백 또는 오류 처리기 ( "errbacks")를 연결할 수있는 Deferred 개체를 소개합니다. Deferred는 기본적으로 함수가 결국 결과를 가져 오는 "약속"입니다.
-
==============================
5.다소 비효율적이지만 비동기 함수를 만들기 위해 데코레이터를 구현할 수 있습니다. 멀티 프로세싱 모듈은 약간의 단점과 겉으로보기에 임의의 제한 사항으로 가득 차 있습니다.하지만 친숙한 인터페이스 뒤에 캡슐화해야 할 이유가 더 많습니다.
다소 비효율적이지만 비동기 함수를 만들기 위해 데코레이터를 구현할 수 있습니다. 멀티 프로세싱 모듈은 약간의 단점과 겉으로보기에 임의의 제한 사항으로 가득 차 있습니다.하지만 친숙한 인터페이스 뒤에 캡슐화해야 할 이유가 더 많습니다.
from inspect import getmodule from multiprocessing import Pool def async(decorated): r'''Wraps a top-level function around an asynchronous dispatcher. when the decorated function is called, a task is submitted to a process pool, and a future object is returned, providing access to an eventual return value. The future object has a blocking get() method to access the task result: it will return immediately if the job is already done, or block until it completes. This decorator won't work on methods, due to limitations in Python's pickling machinery (in principle methods could be made pickleable, but good luck on that). ''' # Keeps the original function visible from the module global namespace, # under a name consistent to its __name__ attribute. This is necessary for # the multiprocessing pickling machinery to work properly. module = getmodule(decorated) decorated.__name__ += '_original' setattr(module, decorated.__name__, decorated) def send(*args, **opts): return async.pool.apply_async(decorated, args, opts) return send
아래 코드는 데코레이터의 사용법을 보여줍니다.
@async def printsum(uid, values): summed = 0 for value in values: summed += value print("Worker %i: sum value is %i" % (uid, summed)) return (uid, summed) if __name__ == '__main__': from random import sample # The process pool must be created inside __main__. async.pool = Pool(4) p = range(0, 1000) results = [] for i in range(4): result = printsum(i, sample(p, 100)) results.append(result) for result in results: print("Worker %i: sum value is %i" % result.get())
실세계의 경우, 장식 자에 대해 좀 더 자세하게 설명하고, 디버깅을 위해 (미래의 인터페이스를 유지하면서) 또는 예외 처리를위한 기능을 해제하는 방법을 제공합니다. 그러나 나는 이것이 원리를 충분히 잘 보여주고 있다고 생각한다.
-
==============================
6.다만
다만
import threading, time def f(): print "f started" time.sleep(3) print "f finished" threading.Thread(target=f).start()
-
==============================
7.내 솔루션은 다음과 같습니다.
내 솔루션은 다음과 같습니다.
import threading class TimeoutError(RuntimeError): pass class AsyncCall(object): def __init__(self, fnc, callback = None): self.Callable = fnc self.Callback = callback def __call__(self, *args, **kwargs): self.Thread = threading.Thread(target = self.run, name = self.Callable.__name__, args = args, kwargs = kwargs) self.Thread.start() return self def wait(self, timeout = None): self.Thread.join(timeout) if self.Thread.isAlive(): raise TimeoutError() else: return self.Result def run(self, *args, **kwargs): self.Result = self.Callable(*args, **kwargs) if self.Callback: self.Callback(self.Result) class AsyncMethod(object): def __init__(self, fnc, callback=None): self.Callable = fnc self.Callback = callback def __call__(self, *args, **kwargs): return AsyncCall(self.Callable, self.Callback)(*args, **kwargs) def Async(fnc = None, callback = None): if fnc == None: def AddAsyncCallback(fnc): return AsyncMethod(fnc, callback) return AddAsyncCallback else: return AsyncMethod(fnc, callback)
요청한대로 정확히 작동합니다.
@Async def fnc(): pass
-
==============================
8.eventlet을 사용할 수 있습니다. 동기식 코드 인 것처럼 보이지만 네트워크를 통해 비동기 적으로 작동하도록 작성할 수 있습니다.
eventlet을 사용할 수 있습니다. 동기식 코드 인 것처럼 보이지만 네트워크를 통해 비동기 적으로 작동하도록 작성할 수 있습니다.
다음은 최소 최소 크롤러의 예입니다.
urls = ["http://www.google.com/intl/en_ALL/images/logo.gif", "https://wiki.secondlife.com/w/images/secondlife.jpg", "http://us.i1.yimg.com/us.yimg.com/i/ww/beta/y3.gif"] import eventlet from eventlet.green import urllib2 def fetch(url): return urllib2.urlopen(url).read() pool = eventlet.GreenPool() for body in pool.imap(fetch, urls): print "got body", len(body)
-
==============================
9.이 기능이 나를 위해 작동하면 함수를 호출하고 새로운 스레드에 자체를 디스패치합니다.
이 기능이 나를 위해 작동하면 함수를 호출하고 새로운 스레드에 자체를 디스패치합니다.
from thread import start_new_thread def dowork(asynchronous=True): if asynchronous: args = (False) start_new_thread(dowork,args) #Call itself on a new thread. else: while True: #do something... time.sleep(60) #sleep for a minute return
-
==============================
10.스레드를 사용하지 않는 이유가 있습니까? 스레딩 클래스를 사용할 수 있습니다. finished () 함수 대신 isAlive ()를 사용하십시오. result () 함수는 스레드를 join ()하여 결과를 검색 할 수 있습니다. 그리고 가능한 경우 run () 및 __init__ 함수를 재정의하여 생성자에 지정된 함수를 호출하고 클래스의 인스턴스에 값을 저장하십시오.
스레드를 사용하지 않는 이유가 있습니까? 스레딩 클래스를 사용할 수 있습니다. finished () 함수 대신 isAlive ()를 사용하십시오. result () 함수는 스레드를 join ()하여 결과를 검색 할 수 있습니다. 그리고 가능한 경우 run () 및 __init__ 함수를 재정의하여 생성자에 지정된 함수를 호출하고 클래스의 인스턴스에 값을 저장하십시오.
-
==============================
11.concurrent.futures (Python 3.2에서 추가됨)를 사용할 수 있습니다.
concurrent.futures (Python 3.2에서 추가됨)를 사용할 수 있습니다.
import time from concurrent.futures import ThreadPoolExecutor def long_computation(duration): for x in range(0, duration): print(x) time.sleep(1) return duration * 2 print('Use polling') with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(long_computation, 5) while not future.done(): print('waiting...') time.sleep(0.5) print(future.result()) print('Use callback') executor = ThreadPoolExecutor(max_workers=1) future = executor.submit(long_computation, 5) future.add_done_callback(lambda f: print(f.result())) print('waiting for callback') executor.shutdown(False) # non-blocking print('shutdown invoked')
-
==============================
12.프로세스를 사용할 수 있습니다. 영원히 (네트워킹과 같은) 사용하는 동안 그것을 사용하려면 다음과 같이하십시오.
프로세스를 사용할 수 있습니다. 영원히 (네트워킹과 같은) 사용하는 동안 그것을 사용하려면 다음과 같이하십시오.
from multiprocessing import Process def foo(): while 1: # Do something p = Process(target = foo) p.start()
한 번 실행하려는 경우 다음과 같이하십시오.
from multiprocessing import Process def foo(): # Do something p = Process(target = foo) p.start() p.join()
from https://stackoverflow.com/questions/1239035/asynchronous-method-call-in-python by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 판다를 사용하여 하나의 데이터 프레임에서 테스트 및 기차 샘플을 만드는 방법은 무엇입니까? (0) | 2018.10.09 |
---|---|
[PYTHON] 올바른 방법으로 곡선을 부드럽게하는 방법은 무엇입니까? (0) | 2018.10.09 |
[PYTHON] Django 사이트에서 HTML을 PDF로 렌더링 (0) | 2018.10.09 |
[PYTHON] 파이썬 대 Cpython (0) | 2018.10.09 |
[PYTHON] Project Euler와의 속도 비교 : C vs Python vs. Erlang vs Haskell (0) | 2018.10.09 |