Reputation: 1338
I'm trying to get to grips with using asyncio to speed up a process of calling an external tool to analyse multiple audio files. I'm working on windows, python 3.6 (anaconda installation) and the problem I'm having here is that the calls don't seem to wait or the results are never received through stdout.
Any ideas?
import os
import asyncio
external_tool = r"C:\path\to\external\tool.exe"
def filepaths_generator(root):
'''
Simple generator to yield filepaths
'''
for path, dirs, files in os.walk(root):
for f in files:
yield os.path.join(path,f)
async def async_subprocess_command(*args):
'''
A function to run the asyncio subprocess call
'''
# Create subprocess
process = 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()
# Return stdout
return stdout.decode().strip()
async def add_external_tool_data_to_dict(filepath):
external_tool_data = await async_subprocess_command(external_tool,filepath)
metadata_dict[filepath] = external_tool_data
return
metadata_dict = {}
loop = asyncio.get_event_loop()
#loop = asyncio.ProactorEventLoop() - Tried this, it doesn't help!
filepaths = filepaths_generator(r"C:\root\path")
tasks = []
for filepath in filepaths:
#Create tasks in for the loop and add to a list
task = loop.create_task(add_external_tool_data_to_dict(filepath))
tasks.append(task)
#Run the tasks
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
print(metadata_dict)
Upvotes: 2
Views: 1044
Reputation: 1338
As per Gerrat's comment, the solution was to use the ProactorEventLoop and add an additional line thereafter:
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
Upvotes: 1
Reputation: 29730
For starters there's this:
On Windows, the default event loop is SelectorEventLoop which does not support subprocesses. ProactorEventLoop should be used instead
Example to use it on Windows:
import asyncio, sys
if sys.platform == 'win32':
loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(loop)
I would start by switching to this alternate event loop.
Upvotes: 6