Importing modules from parent folder

前端 未结 22 2702
梦毁少年i
梦毁少年i 2020-11-21 23:19

I am running Python 2.5.

This is my folder tree:

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(I also have __init

相关标签:
22条回答
  • 2020-11-21 23:49

    Though the original author is probably no longer looking for a solution, but for completeness, there one simple solution. It's to run life.py as a module like this:

    cd ptdraft
    python -m simulations.life.life
    

    This way you can import anything from nib.py as ptdraft directory is in the path.

    0 讨论(0)
  • 2020-11-21 23:50

    It seems that the problem is not related to the module being in a parent directory or anything like that.

    You need to add the directory that contains ptdraft to PYTHONPATH

    You said that import nib worked with you, that probably means that you added ptdraft itself (not its parent) to PYTHONPATH.

    0 讨论(0)
  • 2020-11-21 23:50

    I posted a similar answer also to the question regarding imports from sibling packages. You can see it here.

    Solution without sys.path hacks

    Summary

    • Wrap the code into one folder (e.g. packaged_stuff)
    • Use create setup.py script where you use setuptools.setup().
    • Pip install the package in editable state with pip install -e <myproject_folder>
    • Import using from packaged_stuff.modulename import function_name

    Setup

    I assume the same folder structure as in the question

    .
    └── ptdraft
        ├── __init__.py
        ├── nib.py
        └── simulations
            ├── __init__.py
            └── life
                ├── __init__.py
                └── life.py
    

    I call the . the root folder, and in my case it is located in C:\tmp\test_imports.

    Steps

    1) Add a setup.py to the root folder

    The contents of the setup.py can be simply

    from setuptools import setup, find_packages
    
    setup(name='myproject', version='1.0', packages=find_packages())
    

    Basically "any" setup.py would work. This is just a minimal working example.

    2) Use a virtual environment

    If you are familiar with virtual environments, activate one, and skip to the next step. Usage of virtual environments are not absolutely required, but they will really help you out in the long run (when you have more than 1 project ongoing..). The most basic steps are (run in the root folder)

    • Create virtual env
      • python -m venv venv
    • Activate virtual env
      • . /venv/bin/activate (Linux) or ./venv/Scripts/activate (Win)

    To learn more about this, just Google out "python virtualenv tutorial" or similar. You probably never need any other commands than creating, activating and deactivating.

    Once you have made and activated a virtual environment, your console should give the name of the virtual environment in parenthesis

    PS C:\tmp\test_imports> python -m venv venv
    PS C:\tmp\test_imports> .\venv\Scripts\activate
    (venv) PS C:\tmp\test_imports>
    

    3) pip install your project in editable state

    Install your top level package myproject using pip. The trick is to use the -e flag when doing the install. This way it is installed in an editable state, and all the edits made to the .py files will be automatically included in the installed package.

    In the root directory, run

    pip install -e . (note the dot, it stands for "current directory")

    You can also see that it is installed by using pip freeze

    (venv) PS C:\tmp\test_imports> pip install -e .
    Obtaining file:///C:/tmp/test_imports
    Installing collected packages: myproject
      Running setup.py develop for myproject
    Successfully installed myproject
    (venv) PS C:\tmp\test_imports> pip freeze
    myproject==1.0
    

    4) Import by prepending mainfolder to every import

    In this example, the mainfolder would be ptdraft. This has the advantage that you will not run into name collisions with other module names (from python standard library or 3rd party modules).


    Example Usage

    nib.py

    def function_from_nib():
        print('I am the return value from function_from_nib!')
    

    life.py

    from ptdraft.nib import function_from_nib
    
    if __name__ == '__main__':
        function_from_nib()
    

    Running life.py

    (venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
    I am the return value from function_from_nib!
    
    0 讨论(0)
  • 2020-11-21 23:51

    Above mentioned solutions are also fine. Another solution to this problem is

    If you want to import anything from top level directory. Then,

    from ...module_name import *
    

    Also, if you want to import any module from the parent directory. Then,

    from ..module_name import *
    

    Also, if you want to import any module from the parent directory. Then,

    from ...module_name.another_module import *
    

    This way you can import any particular method if you want to.

    0 讨论(0)
  • 2020-11-21 23:52

    I found the following way works for importing a package from the script's parent directory. In the example, I would like to import functions in env.py from app.db package.

    .
    └── my_application
        └── alembic
            └── env.py
        └── app
            ├── __init__.py
            └── db
    
    import os
    import sys
    currentdir = os.path.dirname(os.path.realpath(__file__))
    parentdir = os.path.dirname(currentdir)
    sys.path.append(parentdir)
    
    0 讨论(0)
  • 2020-11-21 23:52

    For me the shortest and my favorite oneliner for accessing to the parent directory is:

    sys.path.append(os.path.dirname(os.getcwd()))
    

    or:

    sys.path.insert(1, os.path.dirname(os.getcwd()))
    

    os.getcwd() returns the name of the current working directory, os.path.dirname(directory_name) returns the directory name for the passed one.

    Actually, in my opinion Python project architecture should be done the way where no one module from child directory will use any module from the parent directory. If something like this happens it is worth to rethink about the project tree.

    Another way is to add parent directory to PYTHONPATH system environment variable.

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