Tips and tricks from my Telegram-channel @pythonetc, December 2019

    It is a new selection of tips and tricks about Python and programming from my Telegram-channel @pythonetc.

    Previous publications.

    Different asyncio tasks obviously have different stacks. You can view at all of them at any moment using asyncio.all_tasks() to get all currently running tasks and task.get_stack() to get a stack for each task.

    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
            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(
                    print('\t', last_line.strip())
    async def main():
        loop = asyncio.get_event_loop()
        queue = asyncio.Queue()
    loop = asyncio.get_event_loop()

    To avoid messing with the stack object directly and using the linecache module you can call task.print_stack() instead.

    You can translate or delete characters of a string (like the tr utility does) with the translate method of str:

    >>> 'Hello, world!'.translate({
    ...     ord(','): ';',
    ...     ord('o'): '0',
    ... })
    'Hell0; w0rld!'

    The only argument of translate is a dictionary mapping character codes to characters (or codes). It’s usually more convenient to create such a dictionary with str.maketrans static method:

    >>> 'Hello, world!'.translate(str.maketrans({
    ...     ',': ';',
    ...     'o': '0',
    ... }))
    'Hell0; w0rld!'

    Or even:

    >>> 'Hello, world!'.translate(str.maketrans(
    ...     ',o', ';0'
    ... ))
    'Hell0; w0rld!'

    The third argument is for deleting characters:

    >>> tr = str.maketrans(',o', ';0', '!')
    >>> tr
    {44: 59, 111: 48, 33: None}
    >>> 'Hello, world!'.translate(tr)
    'Hell0; w0rld'

    mypy doesn’t yet support recursive types definitions:

    from typing import Optional, Dict
    from pathlib import Path
    TreeDict = Dict[str, 'TreeDict']
    def tree(path: Path) -> TreeDict:
        return {
   tree(f) if f.is_dir() else None
            for f in path.iterdir()

    The error is Cannot resolve name "TreeDict" (possible cyclic definition).

    Stay tuned here:

    Ordinary function just needs to call itself to become recursive. It’s not so simple for generators: you usually have to use yield from for recursive generators:

    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(
            yield name
            if children:
                yield from flatten_tree(children)

    You can use for not only with variables but with any expression. It’s evaluated on every iteration:

    >>> log2 = {}
    >>> key = 1
    >>> for log2[key] in range(100):
    ...     key *= 2
    >>> log2[16]
    >>> log2[1024]
    10 Group
    Building the Internet

    Comments 0

    Only users with full accounts can post comments. Log in, please.