How to properly import python modules from an adjacent folder? - python

I'm trying to follow Learn Python the Hard Way to teach myself python. I want to use the directory structure described in Exercise 46, which for my question I'll simplify down to this:
bin/
app.py
data/
__init__.py
foobar.py
In exercise 50, he says to start the program from the project's top level directory like this:
$ python bin/app.py
Afterwards stating that you start it from the top level directory so the script can access other resources in the project.
But I can't seem to import modules that are in the data folder from app.py. Am I misunderstanding how to setup the directory structure?
Edit: Here's the bare-bones setup I have to try and figure this out
In app.py I have:
import data.foobar
I have __init__.py in the data directory and foobar.py just contains some nonsense like:
class Test:
x = 0
The directory structure matches that of above.

I'm not sure what the exercise asks to do, but your top-level directory needs to be in the PYTHONPATH. Try:
$ export PYTHONPATH=$PYTHONPATH:$PWD
$ python bin/app.py

Related

Python - converting imports to module format

I have a Python package that is structured using imports as if a script is run from the root of the package. So the structure looks something like this:
foo/
script.py
bar/
import_a.py
bar_two/
import_b.py
And the imports within the lower level packages, for example in import_b.py are structured like
from bar import import_a
Obviously this breaks if you want to re-structure this as a package instead of running scripts from the root directory. I need to re-do all the import statements, and add __init__.py files to each subdirectory (this is in python 2.7 as I have to use this with a pre-existing ros kinetic repo, whereas the initial repo was in python 3).
My question is twofold: is there an easy method / script to convert the imports, and is there some way of auto-generating the corresponding __init__.py files?
From the perspective of Python 2.7 this is not even a package since it misses all the __init__.py files (and namespace packages didn't exist back then). So there's not way around creating these __init__.py files. But that should be relatively easy. You can use the following Python snippet from the root of the (to-be-)package:
import os
for item in os.walk('.'):
path = item[0]
with open(os.path.join(path, '__init__.py'), 'w') as fh:
pass
For the modification of import statements there's a way around it. When importing the package you can add the file path of the root __init__.py script to sys.path. That is you can add the following code to foo/__init__.py at the very top:
import os
import sys
sys.path.append(os.path.split(__file__)[0])
That way all imports can be resolved by searching that directory.

Import a python class from an upper directory

I defined a directory named common in the root directory of my project. Basically, there isn't a main file, but rather lots of scripts which I want to directly run.
What I want to do is something like that:
from ../../common/ import <python_file>
Is it possible without too much of a hustle?
Would I need to put __init__.py to make it work?
The use of .. for imports is really a bad practice. What you should do is that. Create a virtualenv using virtualenvwrapper and then use add2virtualenv common
OR
Add the path of the root directory of your project into your PYTHONPATH env variable
export PYTHONPATH=$PYTHONPATH:/path/of/my/project
An __init__.py file must be placed in every folder containing python code

Python: Nosetests with multiple files

This is a broad question because no one seems to have found a solution to it as yet so I think asking to see a working example might prove more useful. So here goes:
Has anyone run a nosetests on a python project using imports of multiple files/packages?
What I mean is, do you have a directory listing such as:
project/
|
|____app/
|___main.py
|___2ndFile.py
|___3rdFile.py
|____tests/
|____main_tests.py
Where your main.py imports multiple files and you perform a nosetests from the project file of utilizing a test script in the main_tests.py file? If so please can you screen shot your import section both of all your main files and your main_tests.py file?
This seems to be a major issue in nosetests, with no apparent solution:
Nosetests Import Error
A test running with nosetests fails with ImportError, but works with python command
https://github.com/nose-devs/nose/issues/978
https://github.com/nose-devs/nose/issues/964
You can't have python modules starting with a digit, so 2ndFile.py, 3rdFile.py won't actually work (rename them).
You'll need an __init__.py inside the app directory, for it to be considered a package, so add that (it can be empty file).
You don't need an __init__.py in the tests directory!
The import statements in main_tests.py should look like from app.main import blah
The absolute path of the project directory needs to be in your sys.path. To achieve this, set an environment variable: export PYTHONPATH=/path/to/project
Now running nosetests should work.

python Import module from a different directory structure

common/src/validation/file1.py
In the common/src/validation/ and common/src/ folder "_init_" is defined.
common/test/validation/file2.py
common/test/validation/case/file3.py
In file2.py and file3.py, I want to import class from file1.py.
Im giving the following line in file2.py and file3.py.:
from file1 import class1
I currently get error:
#ImportError: No module named file1
what should be the sys.path.append ?
If you want to import a file from a folder you should have a file named
__init__.py
in that folder (it could also be a blank file).
You can basically just change PYTHONPATH to common and run from there. Then reference all import paths in relation to that.
like so: (assuming you are in common and your main is in file3.py)
PYTHONPATH=. python test/validation/case/file3.py
Make sure to have __init__.py files in any directory you import (the content of this file doesn't matter)
I usually like putting in the root of every project a run.sh file with some version of this line (pointing to wherever my main func is) in it.
It will usually contain a simple something like that:
#!/bin/bash
source some_env/bin/activate # start the relevant environment if you have one
PYTHONPATH=. python src/main.py # set PYTHONPATH and run
deactivate # exit the relevant environment if started one
Another option is to do this but is't not as elegant.

Python directory/module structure and importing

I'm trying to write a test for my python program, and I've created a /tests directory, where / means the projects root, not system root.
I have all my source files in /myProjectName.
Both directories have a __init__.py file, but project root does not, and both files are empty (do I need a __init__.py in the tests directory ?)
I've tried importing /myProjectName/main.py in /tests/test_main.py, but it doesn't work.
What is the right way to either structure the project directories or import main.py in test_main.py?
I would suggest moving your tests directory to be inside your project directory. Then you can use the answers here to import from the parent directory when you're in tests: Importing modules from parent folder
Otherwise, you can simply set your $PYTHONPATH to point to your project directory when you run tests.
I would like to suggest nose here as it automatically detects the tests and runs them for you
To run the tests, simply do a
$ nosetests
in your project directory
Why not try this line in testmain.py:
import os
os.chdir("/myProjectName/main.py ")
Then execute the script.
Hope it works!

Categories