Samuel Mideksa
Samuel Mideksa

Reputation: 465

How to import a file from a subdirectory in python from a subpackage in another directory?

I have the following directory structure in my home projects folder.

 |ALL-IN-ONE
    |demo
         |__init__.py
         |__main__.py
    |models
         |grpc
             |allinone_server.py

And I want to import from allinone_server.py a function defined in main.py called images_demo. I have tried

from demo.__main__ import images_demo

It is not working. How can I import it? The function I am trying to import is located inside main.py which is inside demo directory. I am trying to import it from the file allinone_server.py in grpc. I guess I have made my question clear now. Here is the whole tree for the project

├── demo
│   ├── __init__.py
│   ├── __main__.py
│   └── __pycache__
│       ├── __init__.cpython-36.pyc
│       └── main.cpython-36.pyc
├── description
├── environment.yml
├── HEAD
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── prepare-commit-msg.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   └── update.sample
├── imgs
│   └── 44.jpg
├── info
│   └── exclude
├── __init__.py
├── loggers
│   ├── __init__.py
│   └── __pycache__
│       └── __init__.cpython-36.pyc
├── models
│   ├── adience_large1.h5
│   ├── adience_small1.h5
│   ├── AgeModel.json
│   ├── detection_age_gender_large1.h5
│   ├── detection_age_gender_small1.h5
│   ├── detection_age_gender_smile_large1.h5
│   ├── detection_age_gender_smile_small1.h5
│   ├── detection_age_large1.h5
│   ├── detection_age_small1.h5
│   ├── detection_large1.h5
│   ├── detection_small1.h5
│   ├── grpc
│   │   ├── adele_2016.jpg
│   │   ├── allinone_client.py
│   │   ├── all_in_one_pb2_grpc.py
│   │   ├── all_in_one_pb2.py
│   │   ├── all_in_one.proto
│   │   ├── allinone_server.py
│   │   ├── benedict_cumberbatch_2014.png
│   │   ├── cat.png
│   │   ├── classroom_in_tanzania.jpg
│   │   ├── decoded1.py
│   │   ├── decoded.py
│   │   ├── elon_musk_2015.jpg
│   │   ├── laos.jpg
│   │   ├── model_face.jpg
│   │   ├── __pycache__
│   │   │   ├── all_in_one_pb2.cpython-36.pyc
│   │   │   ├── all_in_one_pb2_grpc.cpython-36.pyc
│   │   │   └── decoded.cpython-36.pyc
│   │   ├── sophia.jpg
│   │   ├── test
│   │   │   ├── __init__.py
│   │   │   ├── __pycache__
│   │   │   │   └── __init__.cpython-36.pyc
│   │   │   └── test_images
│   │   │       ├── adele_2016.jpg
│   │   │       ├── benedict_cumberbatch_2014.png
│   │   │       ├── classroom_in_tanzania.jpg
│   │   │       ├── elon_musk_2015.jpg
│   │   │       ├── __init__.py
│   │   │       ├── laos.jpg
│   │   │       ├── model_face.jpg
│   │   │       ├── sophia.jpg
│   │   │       ├── waaah.jpg
│   │   │       ├── woman.jpg
│   │   │       └── zebra_stripes.jpg
│   │   ├── waaah.jpg
│   │   ├── woman.jpg
│   │   └── zebra_stripes.jpg

Upvotes: 1

Views: 622

Answers (2)

Sadmi
Sadmi

Reputation: 361

You can't import a function from another folder directly and for that you have to use this:

import sys
sys.path.insert(0, "../../demo/")

Another step is to rename __main__ to main.

here is the exact example that worked for me:

The tree:

.
├── demo
│   ├── __init__.py
│   ├── main.py
│   
└── models
    └── grpc
        └── allinone_server.py

main.py:

def images_demo():
    print("hello there")

The calling file(allinone_server.py):

import sys
sys.path.insert(0, "../../demo/")

import main

main.images_demo()

Upvotes: 1

MichaelCG8
MichaelCG8

Reputation: 579

So you've referred to main.py, but you also have __main__.py in your directory structure. I'll assume that your directory actually contains main.py instead of __main__.py.

To import from levels up in a package, start your import with a period. To import just one function you would use from .main import images_demo

Now, let's start by saying main.py is in grpc/ along with allinone_server.py, then we'll move it to different directories and see how the import changes.

If it were in grpc/ from .main import images_demo

If it were in models/ from ..main import images_demo

If it were in __ALL-IN-ONE/ from ...main import images_demo

If it were in __demo/ from ...__demo.main import images_demo

Every extra period brings you up one level in the hierarchy, then you use the name of the next level down in the target path until you reach where you want to be.

Now let's suppose you wanted to import the whole of main.py. If it were in grpc/ from . import main

If it were in models/ from .. import main

If it were in __ALL-IN-One/ from ... import main

If it were in __demo/ from ...__demo import main

Finally, the dot notation to move up a level only works if the file that uses it is in a package, so this will work fine if at the top level you start your program in a scope outside of this package then use from __ALL-IN-ONE.models.grpc import allinone_server

However, if you run allinone_server.py directly then it will fail to import anything above it as it isn't being imported as part of a package. Try that out, and let me know if that needs better explanation.

Good luck!

Upvotes: 1

Related Questions