Compilation @pythonetc, December 2018



    This is the seventh collection of tips about Python and programming from my author’s @pythonetc channel.

    Previous selections:


    Multiple contexts


    Sometimes you need to run some block of code in several context managers:

    with open('f') as f:
        with open('g') as g:
            with open('h') as h:
                pass

    Since the days of Python 2.7 and 3.1, this can be done with a single expression:

    o = open
    with o('f') as f, o('g') as g, o('h') as h:
        pass

    And before that you could use the function contextlib.nested:

    with nested(o('f'), o('g'), o('h')) as (f, g, h):
        pass

    If you are working with an unspecified number of context managers, it is better to choose more advanced tools. contextlib.ExitStackallows to enter any number of contexts at any time and guarantees exit from them at the end of execution:

    with ExitStack() as stack:
        f = stack.enter_context(o('f'))
        g = stack.enter_context(o('g'))
        other = [
            stack.enter_context(o(filename))
            for filename in filenames
        ]
    

    Objects in interpreter memory


    All objects that are currently in the memory of the interpreter can be accessed using gc.get_objects():

    In : classA:
    ...:     def__init__(self, x):
    ...:         self._x = x
    ...:
    ...:     def__repr__(self):
    ...:         class_name = type(self).__name__
    ...:         x = self._x
    ...:         returnf'{class_name}({x!r})'
    ...:
    In : A(1)
    Out: A(1)
    In : A(2)
    Out: A(2)
    In : A(3)
    Out: A(3)
    In : [x for x in gc.get_objects() if isinstance(x, A)]
    Out: [A(1), A(2), A(3)]
    

    Character Numbers


    In : int('୧৬༣')
    Out: 163

    0 1 2 3 4 5 6 7 8 9- These are not the only characters that are considered numbers. Python follows the rules of Unicode and counts numbers as hundreds of characters. Full list here .

    It matters for functions like int, unicode.isdecimaland even re.match:

    In : int('௯')
    Out: 9
    In : '٢'.isdecimal()
    Out: True
    In : bool(re.match('\d', '౫'))
    Out: True

    Midnight UTC


    >>> bool(datetime(2018, 1, 1).time())
    False>>> bool(datetime(2018, 1, 1, 13, 12, 11).time())
    True

    Before Pyhon 3.5, objects datetime.time()were considered false if they represented midnight UTC. This can lead to unobvious bugs. In the following example, it if notmay not be executed, not because it create_time
    is None, but because it is midnight.

    defcreate(created_time=None) -> None:ifnot created_time:
            created_time = datetime.now().time()

    Around this bug, you can use explicit checks on None: if created_time is None.

    Asynchronous work in FS


    Python does not support asynchronous file operations. To make them non-blocking, you have to use threads.

    For asynchronous code execution in a stream, you need to use the method loop.run_in_executor.

    For you this can be done by a third-party module aiofilesthat provides a convenient and simple interface:

    asyncwith aiofiles.open('filename', mode='r') as f:
        contents = await f.read()
    

    Also popular now: