Importing Modules: _Main_ VS Import as Module

Importing modules: __main__ vs import as module

The __name__ variable always contains the name of the module, except when the file has been loaded into the interpreter as a script instead. Then that variable is set to the string '__main__' instead.

After all, the script is then run as the main file of the whole program, everything else are modules imported directly or indirectly by that main file. By testing the __name__ variable, you can thus detect if a file has been imported as a module, or was run directly.

Internally, modules are given a namespace dictionary, which is stored as part of the metadata for each module, in sys.modules. The main file, the executed script, is stored in that same structure as '__main__'.

But when you import a file as a module, python first looks in sys.modules to see if that module has already been imported before. So, import mod1 means that we first look in sys.modules for the mod1 module. It'll create a new module structure with a namespace if mod1 isn't there yet.

So, if you both run mod1.py as the main file, and later import it as a python module, it'll get two namespace entries in sys.modules. One as '__main__', then later as 'mod1'. These two namespaces are completely separate. Your global var1 is stored in sys.modules['__main__'], but func1B is looking in sys.modules['mod1'] for var1, where it is None.

But when you use python driver.py, driver.py becomes the '__main__' main file of the program, and mod1 will be imported just once into the sys.modules['mod1'] structure. This time round, func1A stores var1 in the sys.modules['mod1'] structure, and that's what func1B will find.

How to import a module as __main__?

The correct answer has been already given however it is confined in a comments (see How to import a module as __main__?
and How to import a module as __main__?).

The same with proper formatting:

import runpy
runpy.run_module("your.module.name", {}, "__main__")

or

import runpy
runpy.run_path("path/to/my/file.py", {}, "__main__")

Why is __main__ name presented as a reason for forbidding relative imports?

It's out of date. That text predates PEP 366, which enables relative import support in the __main__ module.

That text has been in the tutorial in close to its current form since Python 2.5. PEP 366 went in in Python 2.6, but no one realized that the tutorial section was obsolete.


Note that a __main__ module can only use relative imports if Python considers it part of a package. That usually means you have to run it with python -m. Running a file by file path will cause Python to treat it as a top-level module instead of a package submodule.

For example, if I have a directory blah with files __init__.py, foo.py, and bar.py in it, and foo.py contains

from . import bar

and I run python foo.py from inside the blah directory, or python blah/foo.py from above the blah directory, then foo.py is not considered part of a package, and the relative import will fail.

On the other hand, if blah is findable as a package (because I've installed it, or because I'm running Python from the directory above the blah directory), and I do python -m blah.foo to tell Python to run the blah.foo module as the main module, then blah.foo will be considered part of the blah package, and the relative import will succeed.

Use 'import module' or 'from module import'?

The difference between import module and from module import foo is mainly subjective. Pick the one you like best and be consistent in your use of it. Here are some points to help you decide.

import module

  • Pros:
    • Less maintenance of your import statements. Don't need to add any additional imports to start using another item from the module
  • Cons:
    • Typing module.foo in your code can be tedious and redundant (tedium can be minimized by using import module as mo then typing mo.foo)

from module import foo

  • Pros:
    • Less typing to use foo
    • More control over which items of a module can be accessed
  • Cons:
    • To use a new item from the module you have to update your import statement
    • You lose context about foo. For example, it's less clear what ceil() does compared to math.ceil()

Either method is acceptable, but don't use from module import *.

For any reasonable large set of code, if you import * you will likely be cementing it into the module, unable to be removed. This is because it is difficult to determine what items used in the code are coming from 'module', making it easy to get to the point where you think you don't use the import any more but it's extremely difficult to be sure.

How to import modules that are used in both the main code and a module correctly?

Each module X should import all (and only) the modules Y, Z, T, ... whose functionality it requires, without any worry about what other modules Fee, Fie, Foo ... (if any) may have already done part or all of those imports, or may be going to do so in the future.

It would make a module extremely fragile (indeed, it would be the very opposite of modularity!) if each module had to worry about such subtle, "covert-channel" effects.

What other modules Y, Z, T, ..., each module X chooses to import (if any) is part of X's implementation details, and shouldn't concern anybody except the developers who are coding, testing, or maintaining X.

In order to ensure that this is the case, and that this clearly-best strategy of decoupling can and will fully be followed by sane code, Python "caches" modules as they get imported: a module is "loaded" only once per run of a program, the first time anybody imports it (or anything from inside it) -- all other imports use the same object obtained by that first loading, which Python keeps in a cache (which is specified as being the dict sys.modules, but you need to know that detail only for somewhat-advanced programming techniques... don't worry about it, 98.7% of the time -- just remember that "import is cheap"!-).

Sure, a conf.py that you use from several other modules via import conf is definitely a module (you may think you're loading it multiple times, but you aren't unless you're using pretty advanced and deliberate techniques indeed for the purpose) -- why shouldn't it be?

Importing modules that have all its functions inside a main() function

main() typically calls your other functions but does not contain them. Your other functions will lie in the body of the script above main() and can be called in the standard way.

So your test.py example could look like this:

def my_function():
print('Hello')

def my_function2(num):
return num*num

def main():
my_function()
my_function2(5)

if __name__ == "__main__": # if module not imported
main()

How to import package modules from in-package main module

If I want to including blasttofasta.py or run it as script simultaneously mos important is to have directory containing mapp package in sys.path.

This worked for me:

Before importing mapp (or other module from this package) I wrote into blasttofasta.py:

import os
os.sys.path.append(os.path.dirname(os.path.realpath(__file__))+ '/../../')

This append mapp package path and I can run it as script. On the other side is no problem with is included in another package.

Python: importing a sub-package module from both the sub-package and the main package

The reason this is happening is because how python looks for modules and packages when you run a python script as the __main__ script.

When you run python main.py, python will add the parent directory of main.py to the pythonpath, meaning packages and modules within the directory will be importable. When you moved main.py, you changed the directory that was added to the pythonpath.

Generally, you don't want to rely on this mechanism for importing your modules, because it doesn't allow you to move your script and your package and modules are only importable when running that main script. What you should do is make sure your package is installed into a directory that is already in the pythonpath. There are several ways of doing this, but the most common is to create a setup.py script and actually install your python package for the python installation on your computer.



Related Topics



Leave a reply



Submit