将一些代码转换为使用asyncio,我想尽快将控制权交还给asyncio.BaseEventLoop
.这意味着避免阻塞等待.
如果没有异步,我会使用os.stat()
或pathlib.Path.stat()
获得例如文件大小.有没有办法通过asyncio有效地做到这一点?
我可以只包装stat()调用,以便将来与described here类似吗?
解决方法:
os.stat()转换为stat syscall:
$strace python3 -c 'import os; os.stat("/")'
[...]
stat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[...]
这是阻塞的,并且没有办法获得非阻塞的stat syscall.
asyncio通过使用已经存在的非阻塞系统调用来提供非阻塞I / O(请参阅man fcntl,及其O_NONBLOCK标志或ioctl),因此asyncio不会使syscall异步,它以一种不错的方式公开了已经异步的syscall .
仍然可以使用漂亮的ThreadPoolExecutor抽象来使用线程池并行进行阻塞状态调用.
但您可能首先要考虑其他一些参数:
>根据strace -T,stat很快:stat(“ /”,{st_mode = S_IFDIR | 0755,st_size = 4096,…})= 0< 0.000007> ;,可能比启动和同步线程快.
> stat可能在很多情况下受IO限制,因此使用更多的CPU将无济于事
>进行并行I / O可能会破坏对随机访问的良好顺序访问,在这种情况下,物理硬盘驱动器可能会变慢.
但是,使用线程池还可以使您的统计数据更快,例如您要访问分布式文件系统.
您还可以查看functools.lru_cache:如果您在同一个文件或目录上执行多个统计,并且确定它没有更改,则缓存结果可以避免syscall.
总而言之,“保持简单”,“ os.stat”是获取文件大小的有效方法.