necovek 7 days ago

Logging configuration is done at import time for "utils" module.

Imagine code like this:

main.py:

  import logging
  logging.basicConfig(...)

  logging.info("foo") # uses above config
  
  if __name__ == "__main__":
      import utils # your config is overridden with the one in utils
      logging.info("bar") # uses utils configuration
      ...
Or two "commands", one importing utils and another not: they would non-obviously use different logging configuration.

It gets even crazier: you could import utils to set the configuration, override it, but a second import would not re-set it, as module imports are cached.

Basically, don't do it and no unexpected, confusing behaviour anywhere.

  • bumblehean 7 days ago

    As a non Python developer, what would be the use-case(s) for importing a module inside of the main function instead of importing it at the top of main.py with the others?

    • necovek 7 days ago

      Since the entire evaluation and running is dynamic, you don't need to import (and thus evaluate) a module in certain branches.

      Eg. that `if __name__` trick is used to allow a module to be both a runnable script and importable module.

      Top it off with plenty of common libraries being dog-slow to import because they are doing some of the anti-pattern stuff too, and you end up executing a lot of code when you just want to import a single module.

      Eg. I've seen large Python projects that take 75s just importing all the modules because they are listing imports at the top, and many are executing code during import — imagine wanting to run a simple unit test, and your test runner takes 75s just to get to the point where it can run that 0.01s test for your "quick" TDD iteration.

      You can also look at Instagram's approach to solving this over at their engineering blog.