
Es ist eine neue Auswahl von Tipps und Tricks zu Python und Programmierung aus meinem Telegramm-Kanal @pythonetc.
←
Frühere Publikationen .
Unterschiedliche
asyncio
Aufgaben haben offensichtlich unterschiedliche Stapel. Sie können sie jederzeit mit
asyncio.all_tasks()
, um alle aktuell ausgeführten Tasks
task.get_stack()
und
task.get_stack()
, um einen Stapel für jede Task
task.get_stack()
.
import linecache import asyncio import random async def producer(queue): while True: await queue.put(random.random()) await asyncio.sleep(0.01) async def avg_printer(queue): total = 0 cnt = 0 while True: while queue.qsize(): x = await queue.get() total += x cnt += 1 queue.task_done() print(total / cnt) await asyncio.sleep(1) async def monitor(): while True: await asyncio.sleep(1.9) for task in asyncio.all_tasks(): if task is not asyncio.current_task(): f = task.get_stack()[-1] last_line = linecache.getline( f.f_code.co_filename, f.f_lineno, f.f_globals, ) print(task) print('\t', last_line.strip()) print() async def main(): loop = asyncio.get_event_loop() queue = asyncio.Queue() loop.create_task(producer(queue)) loop.create_task(producer(queue)) loop.create_task(producer(queue)) loop.create_task(avg_printer(queue)) loop.create_task(monitor()) loop = asyncio.get_event_loop() loop.create_task(main()) loop.run_forever()
Sie können stattdessen
task.print_stack()
aufrufen, um ein
task.print_stack()
Durcheinander mit dem
linecache
und die Verwendung des
linecache
Moduls zu vermeiden.
Sie können Zeichen eines Strings mit der
translate
Methode von
str
übersetzen oder löschen (wie es das
tr
Dienstprogramm tut):
>>> 'Hello, world!'.translate({ ... ord(','): ';', ... ord('o'): '0', ... }) 'Hell0; w0rld!'
Das einzige Argument für die
translate
ist ein Wörterbuch, das Zeichencodes Zeichen (oder Codes) zuordnet. Es ist normalerweise praktischer, ein solches Wörterbuch mit der statischen Methode
str.maketrans
zu erstellen:
>>> 'Hello, world!'.translate(str.maketrans({ ... ',': ';', ... 'o': '0', ... })) 'Hell0; w0rld!'
Oder sogar:
>>> 'Hello, world!'.translate(str.maketrans( ... ',o', ';0' ... )) 'Hell0; w0rld!'
Das dritte Argument dient zum Löschen von Zeichen:
>>> tr = str.maketrans(',o', ';0', '!') >>> tr {44: 59, 111: 48, 33: None} >>> 'Hello, world!'.translate(tr) 'Hell0; w0rld'
mypy
unterstützt noch keine rekursiven Typdefinitionen:
from typing import Optional, Dict from pathlib import Path TreeDict = Dict[str, 'TreeDict'] def tree(path: Path) -> TreeDict: return { f.name: tree(f) if f.is_dir() else None for f in path.iterdir() }
Der Fehler lautet
Cannot resolve name "TreeDict" (possible cyclic definition)
.
Bleiben Sie hier auf dem Laufenden:
https://github.com/python/mypy/issues/731Gewöhnliche Funktionen müssen sich nur selbst aufrufen, um rekursiv zu werden. Für Generatoren ist das nicht so einfach: Für rekursive Generatoren muss in der Regel die
yield from
werden:
from operator import itemgetter tree = { 'imgs': { '1.png': None, '2.png': None, 'photos': { 'me.jpg': None }, }, 'MANIFEST': None, } def flatten_tree(tree): for name, children in sorted( tree.items(), key=itemgetter(0) ): yield name if children: yield from flatten_tree(children) print(list(flatten_tree(tree)))
Sie können
for
nicht nur mit Variablen, sondern mit jedem Ausdruck verwenden. Es wird bei jeder Iteration ausgewertet:
>>> log2 = {} >>> key = 1 >>> for log2[key] in range(100): ... key *= 2 ... >>> log2[16] 4 >>> log2[1024] 10