I have several times mentioned that executing code when importing a module is a bad practice. At the same time, I could not find anywhere explanations for this statement. Question two.

First, why is code execution when importing a module considered bad practice?

Second, what is considered to be code execution, in the context of this statement? Assigning values ​​to global variables, executing functions or something else? After all, the definition of classes and functions in this module, as well as the import of other modules (in this module, which we import), because this can also be considered "code execution"?

    2 answers 2

    I would not say that this is really a bad practice at all, you just need to approach this matter wisely, to understand what it means, to use it without thinking.

    Reasons to limit this matter, if you think about it, I see the following:

    1. Explicit is better than implicit . You lose control over when this code will be executed, and this may be important. Modules in Python can be imported not only at the top level, but also inside a function or method, which means that the module code will be executed not during the application start, but during the launch of such a function and the execution of the import instruction in it. The functions importing a module, moreover, may not be one, and which of them, and when executed first in your huge application, may not be entirely obvious.

    2. Despite the fact that the module code is executed once at the first boot (in fact, at subsequent imports, it does not even load), to make it run more than once is not so difficult. A good example (not the only way to do it) is considered here .

    3. Your code will be re-executed when you reload your module using reload , which may also be undesirable if this code has certain side effects.

    4. This code can be executed for a long time, which will entail a slowdown in the loading of the module and, as a consequence, the launch of the application.

    At the same time, I want to note that in general this possibility (in moderate quantities) is used everywhere, and, in moderate quantities again, in most cases, there are no problems. For example, a function decorator is the execution of custom code during module loading. Although, if the decorator does not just "change" the decorated function, but has side effects, it may (but not necessarily be far from) a source of problems if you do not understand all these mechanisms.

    For the second question, assigning values (and not the results of user function calls) to global variables, creating functions and classes, importing other modules, that is, in some way, declarative code (which causes execution of not your user logic, but interpreter logic) The context of this statement is not considered code execution.

    In general, the moral is that you just need to clearly understand the possible consequences of code execution when importing a module into Python, and it is reasonable to use this opportunity. The original statement about the inadmissibility of this is akin to saying that the goto is an absolute evil. Yes, thoughtless use is fraught with enormous problems, but at the same time in the same Linux kernel goto for those things where it is really appropriate is used everywhere.

    • one
      Thank you for the detailed response, as well as for the link, a very interesting example with decorators. - Mike

    All of the following is my personal opinion.

    If there is code in your module that should not be executed when imported, but it is executed - this is bad. You need to put it into the if __name__ == '__main__' block. Although, if this is not a module, but simply a one-time script that does not have to be connected somewhere, then there is no need to think about the probable import of the file as a module.

    If there is code in the module that is executed when importing, and it is so intended, then I see nothing wrong with that. Moreover, virtually all module code is executed when importing (including the definitions of classes and functions are actually executed in runtime, because the language is interpretable), so I see no reason to avoid, for example, initializing variables or executing arbitrary code at all when importing.