python import module from a package

后端 未结 3 1047
执念已碎
执念已碎 2021-01-31 12:06

folder structure:


   main.py
   packages 
      __init__.py
      mod.py

main py:

相关标签:
3条回答
  • 2021-01-31 12:52

    Short answer

    So what does the from packages import * really mean inside that __init__.py?

    The __init__.py imports itself.

    Explanation

    You can only import modules, not packages. Packages are just containers for modules or sub-packages. When you "import" a package you actually import the module __init__.py.

    The __init__.py with this content:

    from packages import mod
    

    imports the module mod into __init__.py. Therefore, it will be available in your main.py via packages.mod (remember packages is represented by __init__.py).

    When you change the content of __init__.py to:

    from packages import *
    

    You are importing the module __init__.py, the very same file you are in. This works (a second import just triggers a lookup in sys.modules) but won't give you the content of mod.

    This means, you can use:

    from module import *
    

    but you cannot sensibly use this with an empty __init__.py:

    from package import *
    

    Because package is actually represented by the __init__.py and there is nothing in it yet. You can check this (interactively or in file):

    >>> import packages
    >>> print(packages)
    <module 'packages' from '/.../packages/__init__.py'>
    

    In __init__.py you can write:

    from packages.mod import *
    

    and then in main.py:

    print packages.hello()
    

    works. Because the function hello() is now in the global name space of the file __init__.py.

    As mentioned in the answer by mozman, you can use __all__ in __init__.py to list the modules that should be imported if from packages import * is used. This is designed for this case.

    The __init__.py has only this content:

    __all__ = ['mod']
    

    Now you can do this in main.py:

    from packages import *
    
    print mod.hello()
    

    If you extend your __init__.py:

    __all__ = ['mod']
    
    from packages import *
    

    You can do this in main.py:

    import packages
    
    print packages.mod.hello()
    

    But if you remove the from packages import * from __init__.py:

    __all__ = ['mod'] 
    

    You will get an error:

    AttributeError: 'module' object has no attribute 'mod'
    

    because the __all__ is only used for the from packages import * case. Now we are back to the __init__.py imports itself.

    0 讨论(0)
  • 2021-01-31 13:02

    you can load the modules inside the same packages directly. The following code works and it loads all the modules inside mod.py.

    Inside __init__.py

    from mod import *
    print hello()
    

    Efficient import - loads only hello function

    from mod import hello
    print hello()
    

    In your code, from packages import * you are telling the interpreter to look for a modules inside packages(in the same directory as __init__.py). But it does not exist there. It exist one directory above the __init__.py. (I suspect my terminologies are wrong)

    Here is a reference that explains how to load the containing package itself.

    FOUND IT

    It was very interesting to read about python import mechanisms. Ref1 Ref2 Ref3

    Apparently the parent modules is loaded first. For example, Ref3 states that, the code import mod inside __init__.py is automatically interpreted as packages.mod. Now I have to find out what happens if you write import packages.mod. Ref1 is more up-to-date with python3 conventions. Refer it for more info. Hope this helps you.

    0 讨论(0)
  • 2021-01-31 13:08

    See also: In Python, what exactly does “import *” import?

    adding __all__ to packages.__init__:

    __all__ = ['mod']
    from packages import *
    

    and module 'mod' will be imported, else 'mod' is not in the namespace of 'packages', but I can not explain why 'import *' without __all__ do not import 'mod'.

    0 讨论(0)
提交回复
热议问题