Допустим, у меня есть экземпляр multiprocessing.Lock
(lock
ниже), который я хочу приобрести непосредственно перед тем, как на самом деле начнет работать сопрограмма foo
(скажем, она будет вызвана некоторым будущим вводом / выводом или сигналом, и поэтому я не хочу удерживать блокировку на весь период, когда она заблокирована, а только на время ее работы.) Есть ли способ сделать это без изменения самого тела foo
? Для иллюстрации:
Без блокировки:
await foo()
С блокировкой:
lock.acquire()
await foo()
lock.release()
Насколько я могу судить, это не помогает обернуть foo
внутри другая async
функция, потому что она все еще должна быть await
отредактированной таким же образом. Это также не помогает иметь дело с asyncio.Future
напрямую, потому что все, что я могу сделать, это add_done_callback
. Или любая другая концепция «цепочки» обратных вызовов - это то же самое, что обернуть ее в функцию async
- если я поставлю будущее получения блокировки перед будущим foo
, оно будет эффективно работать сразу же, и блокировка будет удерживается в течение всей продолжительности до тех пор, пока foo
фактически не начнется.
Меняет ли тело foo
единственный путь или есть обходной путь, которого я не вижу?
К Будьте немного более конкретны c в случае, если это проливает свет, моя ситуация на самом деле такова, что foo
- это get
метод экземпляра asyncio.Queue
. Поэтому может быть достаточно подкласса и переопределения этого однострочного метода с помощью двухстрочного, который сначала выполняет желаемое получение блокировки. Или monkeypatch метод в экземпляре. Но это похоже на уродливую территорию.
https://github.com/python/cpython/blob/1e1dbdf23f7a18f53a3257badc3541973831f2c4/Lib/asyncio/queues.py#L57 -L58