【发布时间】:2026-01-14 22:50:02
【问题描述】:
我正在尝试为恢复cwd 的异步函数创建装饰器。我以此为参考:How do I write a decorator that restores the cwd?
这就是我想出的。它没有保留cwd,任何指针?
import os
import asyncio
def preserve_dir(function):
async def decorator(*args, **kwargs):
cwd = os.getcwd()
result = function(*args, **kwargs)
os.chdir(cwd)
return await result
return decorator
@preserve_dir
async def ordinary():
os.chdir("/tmp")
print(os.getcwd())
print(os.getcwd())
asyncio.run(ordinary())
print(os.getcwd())
【问题讨论】:
-
工作目录是全局状态。尝试在异步程序中更改它是危险的,就像使用线程一样。如果两个协程都使用你的
preserve_dir装饰器,你会期望发生什么? -
假设你的程序从
dir1目录开始。协程1启动并将目录更改为dir2,然后协程2启动并将目录更改为dir3,然后协程1结束,然后协程2结束。协程 1 完成后的工作目录是什么?最后的工作目录是什么? -
在所有情况下,我都想在下游代码完成后进入固定目录,与状态无关。保留目录是较大代码库中的固定路径。
-
@user2357112supportsMonica 使用我的回答中的代码,工作目录将打开任一协程的恢复和暂停。 coroutine1 将始终观察
dir2,coroutine2 将观察dir3,而asyncio 的其余部分只会观察dir1作为当前工作目录。最后的工作目录将是dir1。 -
@user4815162342:这种方法的问题在于它与子协程的交互令人困惑。如果用
preserve_dir装饰的协程执行await subcoro(),则subcoro将看到新目录,但如果它使用await asyncio.gather(subcoro1(), subcoro2()),则subcoro1和subcoro2将看到原始目录。结果取决于协程是直接迭代子协程还是调度在事件循环上,这很难控制,通常不需要考虑。
标签: python python-3.x python-asyncio