파이썬에서 동시성을 얻는 방법은 제가 보여주고 자하는 것보다 훨씬 더 정교하고 (적절한) 방법이 있지만 다음과 같은 접근 방식은 매우 간단하고보다 친숙 할 수 있습니다.
n.b. 동일한 시간에 에서 정확히 하나 이상의 연산이 발생할 수 있다는 점에서 이것은 "실제"동시성이 아닙니다. 이것은 파이썬의 GIL로 인해 더 복잡한 방법으로도하기가 어렵습니다.
from collections import defaultdict, deque
import time
from datetime import datetime
class TaskManager:
def __init__(self):
self.tasks = defaultdict(list)
def schedule(self, delta, task):
scheduled_at = time.time() + delta
self.tasks[scheduled_at].append(task)
def tickle(self):
now = time.time()
keys = list(self.tasks.keys())
for k in keys:
if now >= k:
for task in self.tasks.pop(k):
task()
def log(msg):
print("%s - %s" % (datetime.now().strftime("%M:%S"), msg))
tm = TaskManager()
d = deque()
# Possible jobs
def append():
d.append('x')
log("Appended: %s" % d)
tm.schedule(1, append)
def popleft():
try:
d.popleft()
except IndexError:
pass
log("PoppedLeft: %s" % d)
tm.schedule(3, popleft)
# Schedule initial jobs
tm.schedule(1, append)
tm.schedule(3, popleft)
# Run
while True:
tm.tickle()
time.sleep(0.1)
여기 아이디어는 우리가 보류중인 작업 목록과 각 작업이 실행되어야하는 시간을 유지하는 "작업 관리자"를 가지고있다. 우리는 또한 미래의 어떤 시점에서 우리에게 일자리를 예약하도록 작업 관리자에게 알릴 수 있습니다. 이것은 TaskManager
클래스입니다.
처음에는 작업 관리자 인스턴스와 빈 양단 큐를 만듭니다. 그런 다음 (가변 범위를 악용하여) 작업을 정의합니다. 필자는 append
을 deque에 'x'를 추가하고, 빈 상태 일 때 발생하는 오류를 자동으로 무시하여 popleft로 시도하는 popleft
을 정의했습니다.
두 작업 모두 실행 후 작업 관리자로 다시 일정을 잡습니다.
마지막으로 작업 관리자를 주기적으로 "간질"하고 작업 목록을 검토하고 작업이 필요한지 확인하기 위해 중단되지 않는 (주) 시작되었습니다. (예정된 시간이 현재이거나 경과 된 경우 작업이 "시작"됩니다).
예제 코드는 약 1/10th 간격으로 실행되지만 더 자주 수행 될 수도 있지만 도 자주 수행하지 않아야합니다. 빈번히 수행해야합니다. 즉, 1/10 초는 시스템 성능에 영향을 미치지 않으면 서 느려질 수있는 것보다 훨씬 느립니다.
샘플 출력 :
12:24 - Appended: deque(['x'])
12:25 - Appended: deque(['x', 'x'])
12:26 - PoppedLeft: deque(['x'])
12:26 - Appended: deque(['x', 'x'])
12:27 - Appended: deque(['x', 'x', 'x'])
12:28 - Appended: deque(['x', 'x', 'x', 'x'])
12:29 - PoppedLeft: deque(['x', 'x', 'x'])
12:29 - Appended: deque(['x', 'x', 'x', 'x'])
12:30 - Appended: deque(['x', 'x', 'x', 'x', 'x'])
12:31 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x'])
12:32 - PoppedLeft: deque(['x', 'x', 'x', 'x', 'x'])
12:32 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x'])
12:33 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:34 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:35 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:35 - PoppedLeft: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:36 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:37 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:38 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:38 - PoppedLeft: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:39 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:40 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:41 - PoppedLeft: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:41 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:42 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:43 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:44 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:44 - PoppedLeft: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
12:45 - Appended: deque(['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x'])
파이썬 3.4 이상, 그럴 수 ['asyncio.sleep']을 (사용하는 경우 https://docs.python.org/3/library/asyncio-task .html # asyncio.sleep). – jonrsharpe