Can't import own packages in Python 2.7 - python

I'm having some trouble importing own packages in my programs, and so I made a test folder to try and understand what I'm doing wrong.
It's the simplest of things, But I still can't get it to work.
This is my folder structure:
test
> pack1
> __init__.py
> mod1.py
> pack2
> __init__.py
> mod2.py
Both init-files are empty.
mod1 looks like this:
def foo():
print "hello"
and mod2 looks like this
from pack1.mod1 import *
foo()
When running the code in PyCharm, everything works fine! But when trying to execute from cmd I get ImportError: No module named pack1.mod1
Is sys.path.insert(0, "../pack1") my only option, or is there another reason why cmd will not cooperate?

Regardless of version, python has to know where to look for packages. Manipulating sys.path is a quick and dirty option, which will break sometimes in the future, if your code grows more complex. Try making a package and install it via pip install -e or python setup.py develop
(Look for this at the nice distutils introduction)

In regular Python, there are only certain folders that are checked for importing packages and the test folder you have doesn't seem to be one of those files. To change this, edit sys.path in mod2.py and then import pack1.mod1.
mod2.py
import sys
# Add test folder to sys.path
sys.path.append("../")
from pack1.mod1 import *
# Prints "hello"!
foo()
Also, instead of editing sys.path, you could add the pack1 folder into the Lib folder within your Python directory. This will work because this is, by default, one of the folders in sys.path.
Python 2.7
> Lib
> pack1
> __init__.py
> mod1.py
mod2.py
from pack1.mod1 import *
# Prints "hello"!
foo()

You say you execute it via: (Documents)/test/pack2> python mod2.py
Problem is that pack2.mod2.py doesn't know where pack1 is.
Execute it as module:
(Documents)/test> python -m pack2.mod2

If you do not want to modify scripts or directory layout you can use PYTHONPATH environmental variable.
Example
vagrant#h:/tmp/test/pack2$ python mod2.py
Traceback (most recent call last):
File "mod2.py", line 1, in <module>
from pack1.mod1 import *
ImportError: No module named pack1.mod1
vagrant#h:/tmp/test/pack2$ export PYTHONPATH="${PYTHONPATH}:/tmp/test"
vagrant#h:/tmp/test/pack2$ python mod2.py
hello
vagrant#h:/tmp/test/pack2$
More about searching modules - https://docs.python.org/2/tutorial/modules.html#the-module-search-path

Related

'ModuleNotFoundError' when trying to import module from imported package

This is my directory structure:
man/
Mans/
man1.py
MansTest/
SoftLib/
Soft/
SoftWork/
manModules.py
Unittests/
man1test.py
man1.py contains the following import statement, which I do not want to change:
from Soft.SoftWork.manModules import *
man1test.py contains the following import statements:
from ...MansTest.SoftLib import Soft
from ...Mans import man1
I need the second import in man1test.py because man1test.py needs access to a function in man1.py.
My rationale behind the first import (Soft) was to facilitate the aforementioned import statement in man1.py.
Contrary to my expectation, however, the import statement in man1.py gives rise to:
ModuleNotFoundError: No module named 'Soft'
when I run
python3 -m man.MansTest.Unittests.man1test
from a directory above man/.
Is there any way to resolve this error without changing the import statement in man1.py and without adding anything to sys.path?
Edit: python3 -m man.ManTest.Unittests.man1test from the original version of the question changed to python3 -m man.MansTest.Unittests.man1test
FIRST, if you want to be able to access man1.py from man1test.py AND manModules.py from man1.py, you need to properly setup your files as packages and modules.
Packages are a way of structuring Python’s module namespace by using
“dotted module names”. For example, the module name A.B designates a
submodule named B in a package named A.
...
When importing the package, Python searches through the directories on
sys.path looking for the package subdirectory.
The __init__.py files are required to make Python treat the
directories as containing packages; this is done to prevent
directories with a common name, such as string, from unintentionally
hiding valid modules that occur later on the module search path.
You need to set it up to something like this:
man
|- __init__.py
|- Mans
|- __init__.py
|- man1.py
|- MansTest
|- __init.__.py
|- SoftLib
|- Soft
|- __init__.py
|- SoftWork
|- __init__.py
|- manModules.py
|- Unittests
|- __init__.py
|- man1test.py
SECOND, for the "ModuleNotFoundError: No module named 'Soft'" error caused by from ...Mans import man1 in man1test.py, the documented solution to that is to add man1.py to sys.path since Mans is outside the MansTest package. See The Module Search Path from the Python documentation. But if you don't want to modify sys.path directly, you can also modify PYTHONPATH:
sys.path is initialized from these locations:
The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
The installation-dependent default.
THIRD, for from ...MansTest.SoftLib import Soft which you said "was to facilitate the aforementioned import statement in man1.py", that's now how imports work. If you want to import Soft.SoftLib in man1.py, you have to setup man1.py to find Soft.SoftLib and import it there directly.
With that said, here's how I got it to work.
man1.py:
from Soft.SoftWork.manModules import *
# no change to import statement but need to add Soft to PYTHONPATH
def foo():
print("called foo in man1.py")
print("foo call module1 from manModules: " + module1())
man1test.py
# no need for "from ...MansTest.SoftLib import Soft" to facilitate importing..
from ...Mans import man1
man1.foo()
manModules.py
def module1():
return "module1 in manModules"
Terminal output:
$ python3 -m man.MansTest.Unittests.man1test
Traceback (most recent call last):
...
from ...Mans import man1
File "/temp/man/Mans/man1.py", line 2, in <module>
from Soft.SoftWork.manModules import *
ModuleNotFoundError: No module named 'Soft'
$ PYTHONPATH=$PYTHONPATH:/temp/man/MansTest/SoftLib
$ export PYTHONPATH
$ echo $PYTHONPATH
:/temp/man/MansTest/SoftLib
$ python3 -m man.MansTest.Unittests.man1test
called foo in man1.py
foo called module1 from manModules: module1 in manModules
As a suggestion, maybe re-think the purpose of those SoftLib files. Is it some sort of "bridge" between man1.py and man1test.py? The way your files are setup right now, I don't think it's going to work as you expect it to be. Also, it's a bit confusing for the code-under-test (man1.py) to be importing stuff from under the test folder (MansTest).
I had a similar problem, although not the same.
My folders and files had the structure (GUI_ML is the main folder):
GUI_ML
\ Views \ login.py
\ Views \ __ init __.py
\ Controllers \ Control_login.py
\ Controllers \ __ init __.py
I needed to import Control_login.py from login.py. The following code solved my problem:
import sys
import os
myDir = os.getcwd()
sys.path.append(myDir)
from pathlib import Path
path = Path(myDir)
a=str(path.parent.absolute())
sys.path.append(a)
from Controllers.Control_login import Control_login
For me when I created a file and saved it as python file, I was getting this error during importing.
I had to create a filename with the type ".py" , like filename.py and then save it as a python file.
post trying to import the file worked for me.
some package name and module name might be the same. this conflict is also responded with this error.
I was having a similar issue where I forgot to put a __init__.py in the module and spend a lot of time wasting trying to understand what's wrong.
Another solution depends on where you run this code from.
Assuming the OP's directory structure:
man/
Mans/
man1.py
MansTest/
SoftLib/
Soft/
SoftWork/
manModules.py
Unittests/
man1test.py
If you try running python Mans/man1.py (from the man directory), you would have to do the following two things for this to work:
Change the import line in man1.py to from ManTest.SoftLib.Soft.SoftWork.manModules import *
If not already there, add to your system environment variable. Key PYTHONPATH, value .

How to split python script into several files using relative imports?

I have import.py script. I want to extract some code into a separate file, say, m1.py:
$ ls
import.py m1.py
$ cat import.py
from .m1 import a
a()
$ cat m1.py
def a():
print('it works')
$ python import.py
Traceback (most recent call last):
File "import.py", line 1, in <module>
from .m1 import a
ModuleNotFoundError: No module named '__main__.m1'; '__main__' is not a package
When I switch to absolute import, it works. But I don't want accidentally importing other module. I want to be sure module from script's directory is imported. How do I make it work? Or what am I doing wrong?
If you're not overriding the built in modules. By default, python looks first in your current directory for the file name you want to import. So if there is another script having the same name in another directory, only the one you have in the current directory is the one that will be imported.
Then, you could import using the absolute import.
from m1 import a
a()
You can check this post out, for more infrotmation about importing in python.
To make sure that the one your importing isn't the built in. You can create your own package in the current directory for example,"my_package" and have your module m1 moved in it. Then you can import by:
from my_package import m1
m1.a()
Add __init__.py in the directory where m1.py is.
EDIT : Run it as a package from the previous working directory. cd .. && python -m prev_dir.import

Python: importing a sub-package module from both the sub-package and the main package

Here we go with my first ever stackoverflow quesion. I did search for an answer, but couldn't find a clear one. Here's the situation. I've got a structure like this:
myapp
package/
__init.py__
main.py
mod1.py
mod2.py
Now, in this scenario, from main.py I am importing mod1.py, which also needs to be imported by mod2.py. Everything works fine, my imports look like this:
main.py:
from mod1 import Class1
mod2.py:
from mod1 import Class1
However, I need to move my main.py to the main folder structure, like this:
myapp
main.py
package/
__init.py__
mod1.py
mod2.py
And now what happens is that of course I need to change the way I import mod1 inside main.py:
from package.mod1 import Class1
However, what also happens is that in order not to get an "ImportError: No module named 'mod1'", I have make the same type of change inside mod2.py:
from package.mod1 import Class1
Why is that? mod2 is in the same folder/pakcage as mod1, so why - upon modifying main.py - am I expected to modify my import inside mod2?
The reason this is happening is because how python looks for modules and packages when you run a python script as the __main__ script.
When you run python main.py, python will add the parent directory of main.py to the pythonpath, meaning packages and modules within the directory will be importable. When you moved main.py, you changed the directory that was added to the pythonpath.
Generally, you don't want to rely on this mechanism for importing your modules, because it doesn't allow you to move your script and your package and modules are only importable when running that main script. What you should do is make sure your package is installed into a directory that is already in the pythonpath. There are several ways of doing this, but the most common is to create a setup.py script and actually install your python package for the python installation on your computer.

Python cannot import module from subdirectory even with a file named __init.py__ in the directory

I know this question has been asked many times here and I'v probably read most of the answers (including this and that) as well as the python documentation but still can not find an answer to my very simple import problem. It's so simple that I must miss something stupid but I don't see it yet.
I have setup the following structure:
myproject
myscript.py
MyPackage
__init.py__
mymodule.py
I just want to load mymodule.py from myscript.py (or the commandline python interpreter which should be the same).
myscript.py contains:
#!/usr/bin/python
import MyPackage
__init.py__ contains:
from . import mymodule
mymodule.py contains
#!/usr/bin/python
def myfunction():
print "mymessage"
My goal is to call myfunction from myscript.py but if I try to call the module I get
$python myscript.py
Traceback (most recent call last):
File "myscript.py", line 2, in <module>
import MyPackage
ImportError: No module named MyPackage
What I already tried:
I tried everything under OSX and Ubuntu Linux to reduce the possibility of a faulty python installation.
I set the PYTHONPATH environment variable to the myproject directory as well as to . and to both.
I left __init.py__ blank
I tried the import statements also from the python interpreter started from the myproject directory
I tried the following import statements:
from MyPackage import mymodule
import MyPackage.mymodule
import MyPackage.mymodule as module
all without success (same error message).
If I put mymodule.py in the project directory without using a package, import works fine. But I don't see why the import from the subpackages is not working.
Any idea how I can get that to work?
Thanks for help!
While editing the formatting of your post, I noticed you're calling your file __init.py_. That causes python to not recognize your MyPackage directory as a package, hence the ImportError: No module named MyPackage.
It should instead be __init__.py (Name __init__, extension .py). Then it will work, your project structure and import statements are otherwise correct.
One minor point though: You should also use lower_underscore style for naming your package. Packages are modules as well in Python, and they should follow the same naming conventions. See PEP8 for details on recommended style and naming conventions. This is just a convention though, it has nothing to do with your problem.

How to import your package/modules from a script in bin folder in python

When organising python project, this structure seems to be a standard way of doing it:
myproject\
bin\
myscript
mypackage\
__init__.py
core.py
tests\
__init__.py
mypackage_tests.py
setup.py
My question is, how do I import my core.py so I can use it in myscript?
both __init__.py files are empty.
Content of myscript:
#!/usr/bin/env python
from mypackage import core
if __name__ == '__main__':
core.main()
Content of core.py
def main():
print 'hello'
When I run myscript from inside myproject directory, I get the following error:
Traceback (most recent call last):
File "bin/myscript", line 2, in <module>
from mypackage import core
ImportError: No module named mypackage
What am I missing?
Usually, setup.py should install the package in a place where the Python interpreter can find it, so after installation import mypackage will work. To facilitate running the scripts in bin right from the development tree, I'd usually simply add a simlink to ../mypackage/ to the bin directory. Of course, this requires a filesystem supporting symlinks…
I'm not sure if there is a "best choice", but the following is my normal practice:
Put whatever script I wanna run in /bin
do "python -m bin.script" in the dir myproject
When importing in script.py, consider the dir in which script.py is sitting as root. So
from ..mypackage import core
If the system supports symlink, it's a better choice.
I usually add my bin path into $PYTHONPATH, that will enable python to look for asked module in bin directory too.
export PYTHONPATH=/home/username/bin:$PYTHONPATH
$ python
import module_from_bin
I solved the issue following setuptools specifications.
In setup.py you can specify the modules as an argument for the function setup():
packages = find_packages()
This finds all modules.
p.s. you have to import this function: from setuptools import setup, find_packages

Categories