简体   繁体   中英

How to import a python file from another folder in Python 3.5 on OSX?

I use Python 3.5 and my project structure is like this:

Project/
    App/
        myApp.py
    Libraries/
        myLibA.py
        myLibB.py

I want to import myLibA.py in myApp.py

If I simply write from Libraries import myLibA I end up with this error :

ImportError: No module named Libraries.

I found the Q/A Importing files from different folder in Python , from which I adapted my own solution, adding this at the beginning of myApp.py in order to add my Project folder to the Python Path :

import sys
sys.path.insert(0, sys.path[0] + "..")

This worked well on Windows, but when I run myApp.py from the same project on OSX (10.9) I see the same error message, my module is not found.

To reproduce my issue it's very simple. Just fill the Python files like this :

myApp.py :

import sys
sys.path.insert(0, sys.path[0] + "..")

from Libraries import myLibA

if __name__ == '__main__':
    myLibA.print_hello()

myLibA.py :

def print_hello():
    print("Hello")

I don't understand why the Python Path method doesn't work here. Anyway, I'm looking for a solution that keeps the Python file compatible with Windows and that is contained in the sources (in the Python files). I've seen a few console hooks but I'm not satisfied with that because I want to be able to clone the project on any OSX/Windows PC with Python 3.5, and just run myApp.py. I'm looking for a solution that doesn't involve any library not natively present in Python 3.5.

Is there another way to achieve this ?

(If not, is it because it is somehow not pythonic to organize a project like this? As a C developer I might have the wrong approach)

Add __init__.py to your Libraries directory. That file can be empty, and it magically turns the Libraries directory into a package . Now:

import sys
import os.path
libdir = os.path.dirname(__file__)
sys.path.append(os.path.split(libdir)[0])   

from Libraries import myLibA

if __name__ == '__main__':
    myLibA.print_hello()

The __file__ special variable gives the filename of the current script. os.path.dirname() gives the directory it resides in, and os.path.split(libdir)[0] gives its parent directory. This should work wherever the script is called from.

I am using append rather than insert . It is generally advised that user directories are searched last, and also append is more efficient than insert in the C Python implementation.

You should have __init__.py inside every folder that you want to import. Also a common project structure for a python project is this:

Project/ 
Libraries/         <-- this will contain app specific code (Libraries)
    __init__.py
    myLibA.py
    myLibB.py
main.py

Where main.py will contain the entry code of you app, just like C's main(), for example

from Libraries import myLibA

if __name__ == '__main__':
    myLibA.print_hello()

No need to tinker with sys.path in runtime.

This Question is somewhat similar. My favourite answer suggests a project structure like this in your case:

Project/
    myApp.py
    Libraries/
        __init__.py
        myLibA.py
        myLibB.py

With the library code in myLibA.py unchanged the app code and import would look like this:

from Libraries import myLibA

if __name__ == "__main__":
    myLibA.print_hello()

Edit 1:

When the requested folder structure is necessary, this change to the myApp.py file:

import sys
import os
sys.path.append(os.path.abspath(".."))

works too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM