我有这段代码:
import os
import time
import asyncio
async def run_command(*args):
"""
Example from:
http://asyncio.readthedocs.io/en/latest/subprocess.html
"""
# Create subprocess
process = await asyncio.create_subprocess_exec(
*args,
# stdout must a pipe to be accessible as process.stdout
stdout=asyncio.subprocess.PIPE)
# Wait for the subprocess to finish
stdout, stderr = await process.communicate()
# Result
result = stdout.decode().strip()
# Return stdout
return result
def run_asyncio_commands(tasks):
"""Run tasks using asyncio and return results"""
loop = asyncio.get_event_loop()
commands = asyncio.gather(*tasks) # Unpack list using *
results = loop.run_until_complete(commands)
loop.close()
return results
if __name__ == '__main__':
start = time.time()
cmds = [
['du', '-sh', '/Users/fredrik/Desktop'],
['du', '-sh', '/Users/fredrik'],
['du', '-sh', '/Users/fredrik/Pictures']
]
tasks = []
for cmd in cmds:
tasks.append(run_command(*cmd))
results = run_asyncio_commands(tasks)
print(results)
end = time.time()
print('Script ran in', str(end - start), 'seconds')
当我在 Mac 上的 Python 3.6.1 中运行该代码时,我得到:
['780K\t/Users/fredrik/Desktop', '46G\t/Users/fredrik', '52M\t/Users/fredrik/Pictures']
Script ran in 6.405519008636475 seconds
但是当我在 Windows 上运行相同的脚本时(但将
du
命令替换为某些内容)它适用于 Windows),也适用于 Python 3.6.1,我得到这个:
Traceback (most recent call last):
File "C:\Users\iruser\Desktop\asynciotest.py", line 66, in <module>
results = run_asyncio_commands(tasks)
File "C:\Users\iruser\Desktop\asynciotest.py", line 41, in run_asyncio_commands
results = loop.run_until_complete(commands)
File "C:\Users\fredrik\condaenvs\dev_py36\lib\asyncio\base_events.py", line 466, in run_until_complete
return future.result()
File "C:\Users\iruser\Desktop\asynciotest.py", line 16, in run_command
stdout=asyncio.subprocess.PIPE)
File "C:\Users\fredrik\condaenvs\dev_py36\lib\asyncio\subprocess.py", line 225, in create_subprocess_exec
stderr=stderr, **kwds)
File "C:\Users\fredrik\condaenvs\dev_py36\lib\asyncio\base_events.py", line 1190, in subprocess_exec
bufsize, **kwargs)
File "C:\Users\fredrik\condaenvs\dev_py36\lib\asyncio\coroutines.py", line 210, in coro
res = func(*args, **kw)
File "C:\Users\fredrik\condaenvs\dev_py36\lib\asyncio\base_events.py", line 340, in _make_subprocess_transp
ort
raise NotImplementedError
NotImplementedError
这是我在 Windows 上替换 Unix 命令的内容:
cmds = [['C:/Windows/system32/HOSTNAME.EXE']]
Python 和 Windows 版本信息:
Python 3.6.1 | packaged by conda-forge | (default, May 23 2017, 14:21:39) [MSC v.1900 64 bit (AMD64)] on win32
Windows 10 Pro, version 1703, OS build 15063.413
这个错误信息 “NotImplementedError: ” 在 Windows 上使用 asyncio 时通常意味着你正尝试使用一个尚未在 Windows 上实现的 asyncio 的特性。具体来说,你在代码中遇到的问题在于使用
asyncio.create_subprocess_exec
时将
stdout
或
stderr
设置为
asyncio.subprocess.PIPE
。
在 Windows 上,
asyncio
的子进程管道处理方式与 Unix 系统不同。在 Windows 上,你需要使用线程来处理来自子进程的标准输出和标准错误流。
以下是如何在 Windows 上修改你的代码以使其正常工作的示例:
import os
import time
import asyncio
async def run_command(*args):
"""Runs a command asynchronously."""
# Launch the subprocess
process = await asyncio.create_subprocess_exec(
*args,
# Do not redirect stdout or stderr
stdout=None,
stderr=None,
)
# Wait for the subprocess to finish
await process.wait()
# Return the return code
return process.returncode
async def run_asyncio_commands(tasks):
"""Runs tasks using asyncio and returns results."""
results = await asyncio.gather(*tasks)
return results
if __name__ == "__main__":
start = time.time()
cmds = [['C:/Windows/system32/HOSTNAME.EXE']]
tasks = [run_command(*cmd) for cmd in cmds]
results = asyncio.run(run_asyncio_commands(tasks))
print(f"Return codes: {results}")
end = time.time()
print(f"Script ran in {end - start:.4f} seconds")
这个修改后的代码中,我们不再尝试使用管道来读取子进程的输出。我们只是启动子进程,等待它完成,然后返回它的返回码。
如果你需要从子进程中捕获输出,你需要使用一个不同的方法,比如使用一个线程来读取子进程的输出流。
标签:python,windows,subprocess,python-asyncio From: 44633458