编辑:正如指出的蒂埃里Lathuille,PEP567,在那里ContextVar被引入,却没有设计地址发生器(不像撤回PEP550)。尽管如此,主要问题仍然存在。如何编写可在多个线程,生成器和asyncio任务中正常运行的有状态上下文管理器?
我有一个带有一些可以在不同“模式”下运行的功能的库,因此可以通过本地上下文来更改其行为。我正在查看contextvars可靠地实现此功能的模块,因此可以在不同的线程,异步上下文等环境中使用它。但是,我很难获得一个正确的简单示例。考虑以下最小设置:
from contextlib import contextmanager
from contextvars import ContextVar
MODE = ContextVar('mode', default=0)
@contextmanager
def use_mode(mode):
t = MODE.set(mode)
try:
yield
finally:
MODE.reset(t)
def print_mode():
print(f'Mode {MODE.get()}')
Run Code Online (Sandbox Code Playgroud)
这是一个带有生成器功能的小测试:
def first():
print('Start first')
print_mode()
with use_mode(1):
print('In first: with use_mode(1)')
print('In first: start second')
it = second()
next(it)
print('In first: back from second')
print_mode()
print('In first: continue second')
next(it, None)
print('In first: finish')
def second():
print('Start second')
print_mode() …Run Code Online (Sandbox Code Playgroud) 我在Ubuntu 18.04上将Flask 1.0.2与Python 3.6一起使用。我的应用程序应使用asyncio并asyncio.create_subprocess_exec()启动后台脚本,从中读取stdout,然后在脚本完成后返回状态。
我基本上是想从这篇文章中实现一个答案: 在Python的subprocess.PIPE上非阻塞读取
该脚本已成功启动,并且从中获得了所有预期的输出,但是问题是它从不返回(意味着Killing subprocess now从不到达该行)。当我ps从Linux终端检查进程列表()时,后台脚本已退出。
我在做什么错,如何才能成功摆脱困境async for line in process.stdout?
导入后,在文件顶部,创建事件循环:
# Create a loop to run all the tasks in.
global eventLoop ; asyncio.set_event_loop(None)
eventLoop = asyncio.new_event_loop()
asyncio.get_child_watcher().attach_loop(eventLoop)
Run Code Online (Sandbox Code Playgroud)
我在路线上方定义了异步协程:
async def readAsyncFunctionAndKill(cmd):
# Use global event loop
global eventLoop
print("[%s] Starting async Training Script ..." % (os.path.basename(__file__)))
process = await asyncio.create_subprocess_exec(cmd,stdout=PIPE,loop=eventLoop)
print("[%s] Starting to read stdout ..." % (os.path.basename(__file__)))
async for line in process.stdout:
line = line.decode(locale.getpreferredencoding(False)) …Run Code Online (Sandbox Code Playgroud)