Stochern nur meine Zehe in asynchrone Programmierung in Python, und lief in eine interessante Anwendung für die ich Dateigrößen auf etwa 10 Dateien auf ~ 100 Maschinen sammeln müssen, um zu sehen, welche Maschinen Aren sind Log-Dateien nicht korrekt löschen.Async Coroutine scheint nicht zu Ende
Mein synchroner Ansatz war:
File_info = namedtuple("File_info", "machineinfo size")
machines = utils.list_machines() # the computers being queried
# each machine object has attributes like "name", "IP", and "site_id" among others
file_sizes = {}
# {filename: [File_info, ...], ...}
for m in machines:
print(f"Processing {m}...") # this is "Processing {m}...".format(m=m)
# isn't Python 3.6 awesome?!
for path in glob.glob(f"//{m.IP}/somedir/*.dbf"):
fname = os.path.split(path)[-1].lower()
machineinfo = (m.site_id, m.name)
size = os.stat(path).st_size
file_sizes.setdefault(fname, []).append(File_info(registerinfo, size))
Dies funktioniert gut, aber dauert eine lange Zeit mit den Netzwerk-Operationen all diese Klecksen und Statistiken zu ziehen. Ich wollte die async/await-Syntax von Python 3.5 mit asyncio verwenden, um diese Aufrufe zu asynchronisieren. Hier ist, was ich kam mit:
File_info = namedtuple("File_info", "machineinfo size")
machines = utils.list_machines()
file_sizes = {}
# {filename: [File_info, ...], ...}
async def getfilesizes(machine, loop):
machineinfo = machine.site_id, machine.name
paths = glob.glob(f"//{machine.IP}/somedir/*.dbf")
coros = [getsize(path) for path in paths]
results = loop.run_until_complete(asyncio.gather(*coros))
sizes = {fname: File_info(machineinfo, size) for (fname, size) in results}
return sizes
async def getsize(path):
return os.path.split(path)[-1], os.stat(path).st_size
loop = asyncio.get_event_loop()
results = loop.run_until_complete(asyncio.gather(*(getfilesizes(m, loop) for m in machines)))
for result in results:
file_sizes.update(result)
# I have a problem here since my dict values are lists that need to extend
# not overwrite, but that's not relevant for the error I'm getting
jedoch das Skript innerhalb des äußeren loop.run_until_complete
Abschnitt hängt. Was mache ich falsch?
Eine Coroutine, die eine andere Coroutine ausführen oder das Ergebnis einer Zukunft erhalten will, soll sie "erwarten", nicht mit "run_until_complete" abliefern. – user2357112
Soll ich auf asyncio.gather (...) warten? –
@ user2357112 Nun, ich werde ein Affe Onkel sein, das war einfach. Ich bin mir nicht sicher, warum ich die Verbindung nicht hergestellt habe, dass "asyncio.gather" ein "Future" -Objekt gibt, damit ich es einfach wegstellen kann, anstatt es zu planen. Möchten Sie das als Antwort aufschreiben? Sonst antworte ich selbst. –