How to import a Python module from a sibling folder? - python

I have gone through many Python relative import questions but I can't understand the issue/get it to work.
My directory structure is:
Driver.py
A/
Account.py
__init__.py
B/
Test.py
__init__.py
Driver.py
from B import Test
Account.py
class Account:
def __init__(self):
self.money = 0
Test.py
from ..A import Account
When I try to run:
python Driver.py
I get the error
Traceback (most recent call last):
from B import Test
File "B/Test.py", line 1, in <module> from ..A import Account
ValueError: Attempted relative import beyond toplevel package

This is happening because A and B are independent, unrelated, packages as far as Python is concerned.
Create a __init__.py in the same directory as Driver.py and everything should work as expected.

In my case adding __init__.py was not enough. You also have to append the path of the parent directory if you get module not found error.
root :
|
|__SiblingA:
| \__A.py
|
|__SiblingB:
| \_ __init__.py
| \__B.py
|
To import B.py from A.py, you have to do the following
import sys
# append the path of the parent directory
sys.path.append("..")
from SiblingB import B
print("B is successfully imported!")

The reason for
ValueError: Attempted relative import beyond toplevel package
is that A is the same directory level as Driver.py. Hence, ..A in from ..A import Account is beyond top-level package.
You can solve this by create a new folder named AandB together with __init__py in this new folder, and then move A and B folders into AandB folder. The directory structure is as following:
Correspondingly, the content in Driver.py should be modified as from AandB.B import Test.

Related

Importing module from "outer" directory [Python]

I have seen a lot of answers over this simple problem but I can't find a good solution for such, even a workable solution; the problem is, I have this proyect structure
parent_folder
|
|__folder1
| |_____ __init__.py
| |_____ file1.py
|
|__folder2
|_____ __init__.py
|_____file2.py
I want to call a function (lets name it function2) from file2.py inside file1.py, but when doing an import like this:
# inside file1.py
from folder2.file import function2
I get the following error:
ModuleNotFoundError: No module named 'folder2'
Then I tried using absolute import, so the code looked like:
# inside file1.py
from ..folder2.file2 import function2
And I get the following error:
ImportError: attempted relative import with no known parent package
And finally I tried adding such directory to my path using the following code:
#inside file1.py
import sys
sys.path.append("..")
from ..folder2.file2 import function2
And still, get the same error:
ImportError: attempted relative import with no known parent package
What is the definitive CLEAN solution for such problem?,I would appreciate an answer, thanks
NOTE: My current Python version is 3.8 and the code is running under Windows 10
file1.py
import os
import sys
sys.path.append(os.path.dirname(os.getcwd()))
from folder2.file2 import function2

python 3.0 - Import file within the given directory [duplicate]

I have this folder structure:
application
├── app
│   └── folder
│   └── file.py
└── app2
└── some_folder
└── some_file.py
How can I import a function from file.py, from within some_file.py? I tried:
from application.app.folder.file import func_name
but it doesn't work.
Note: This answer was intended for a very specific question. For most programmers coming here from a search engine, this is not the answer you are looking for. Typically you would structure your files into packages (see other answers) instead of modifying the search path.
By default, you can't. When importing a file, Python only searches the directory that the entry-point script is running from and sys.path which includes locations such as the package installation directory (it's actually a little more complex than this, but this covers most cases).
However, you can add to the Python path at runtime:
# some_file.py
import sys
# caution: path[0] is reserved for script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')
import file
Nothing wrong with:
from application.app.folder.file import func_name
Just make sure folder also contains an __init__.py, this allows it to be included as a package. Not sure why the other answers talk about PYTHONPATH.
When modules are in parallel locations, as in the question:
application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py
This shorthand makes one module visible to the other:
import sys
sys.path.append('../')
First import sys in name-file.py
import sys
Second append the folder path in name-file.py
sys.path.insert(0, '/the/folder/path/name-package/')
Third Make a blank file called __ init __.py in your subdirectory (this tells Python it is a package)
name-file.py
name-package
__ init __.py
name-module.py
Fourth import the module inside the folder in name-file.py
from name-package import name-module
I think an ad-hoc way would be to use the environment variable PYTHONPATH as described in the documentation: Python2, Python3
# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH
# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
Your problem is that Python is looking in the Python directory for this file and not finding it. You must specify that you are talking about the directory that you are in and not the Python one.
To do this you change this:
from application.app.folder.file import func_name
to this:
from .application.app.folder.file import func_name
By adding the dot you are saying look in this folder for the application folder instead of looking in the Python directory.
Try Python's relative imports:
from ...app.folder.file import func_name
Every leading dot is another higher level in the hierarchy beginning with the current directory.
Problems? If this isn't working for you then you probably are getting bit by the many gotcha's relative imports has.
Read answers and comments for more details:
How to fix "Attempted relative import in non-package" even with __init__.py
Hint: have __init__.py at every directory level. You might need python -m application.app2.some_folder.some_file (leaving off .py) which you run from the top level directory or have that top level directory in your PYTHONPATH. Phew!
The answers here are lacking in clarity, this is tested on Python 3.6
With this folder structure:
main.py
|
---- myfolder/myfile.py
Where myfile.py has the content:
def myfunc():
print('hello')
The import statement in main.py is:
from myfolder.myfile import myfunc
myfunc()
and this will print hello.
In Python 3.4 and later, you can import from a source file directly (link to documentation). This is not the simplest solution, but I'm including this answer for completeness.
Here is an example. First, the file to be imported, named foo.py:
def announce():
print("Imported!")
The code that imports the file above, inspired heavily by the example in the documentation:
import importlib.util
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
foo = module_from_file("foo", "/path/to/foo.py")
if __name__ == "__main__":
print(foo)
print(dir(foo))
foo.announce()
The output:
<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
Note that the variable name, the module name, and the filename need not match. This code still works:
import importlib.util
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
baz = module_from_file("bar", "/path/to/foo.py")
if __name__ == "__main__":
print(baz)
print(dir(baz))
baz.announce()
The output:
<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
Programmatically importing modules was introduced in Python 3.1 and gives you more control over how modules are imported. Refer to the documentation for more information.
From what I know, add an __init__.py file directly in the folder of the functions you want to import will do the job.
Using sys.path.append with an absolute path is not ideal when moving the application to other environments. Using a relative path won't always work because the current working directory depends on how the script was invoked.
Since the application folder structure is fixed, we can use os.path to get the full path of the module we wish to import. For example, if this is the structure:
/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py
And let's say that you want to import the mango module. You could do the following in vanilla.py:
import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango
Of course, you don't need the mango_dir variable.
To understand how this works look at this interactive session example:
>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
'/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>>
>>> newdir
'/home/me/application/app2/another_folder'
>>>
And check the os.path documentation.
Also worth noting that dealing with multiple folders is made easier when using packages, as one can use dotted module names.
I was faced with the same challenge, especially when importing multiple files, this is how I managed to overcome it.
import os, sys
from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))
from root_folder import file_name
Considering application as the root directory for your python project, create an empty __init__.py file in application, app and folder folders. Then in your some_file.py make changes as follows to get the definition of func_name:
import sys
sys.path.insert(0, r'/from/root/directory/application')
from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()
Worked for me in python3 on linux
import sys
sys.path.append(pathToFolderContainingScripts)
from scriptName import functionName #scriptName without .py extension
The best practice for creating a package can be running and accessing the other modules from a module like main_module.py at highest level directory.
This structure demonstrates you can use and access sub package, parent package, or same level packages and modules by using a top level directory file main_module.py.
Create and run these files and folders for testing:
package/
|
|----- __init__.py (Empty file)
|------- main_module.py (Contains: import subpackage_1.module_1)
|------- module_0.py (Contains: print('module_0 at parent directory, is imported'))
|
|
|------- subpackage_1/
| |
| |----- __init__.py (Empty file)
| |----- module_1.py (Contains: print('importing other modules from module_1...')
| | import module_0
| | import subpackage_2.module_2
| | import subpackage_1.sub_subpackage_3.module_3)
| |----- photo.png
| |
| |
| |----- sub_subpackage_3/
| |
| |----- __init__.py (Empty file)
| |----- module_3.py (Contains: print('module_3 at sub directory, is imported'))
|
|------- subpackage_2/
| |
| |----- __init__.py (Empty file)
| |----- module_2.py (Contains: print('module_2 at same level directory, is imported'))
Now run main_module.py
the output is
>>>'importing other modules from module_1...'
'module_0 at parent directory, is imported'
'module_2 at same level directory, is imported'
'module_3 at sub directory, is imported'
Opening pictures and files note:
In a package structure if you want to access a photo, use absolute directory from highest level directory.
let's Suppose you are running main_module.py and you want to open photo.png inside module_1.py.
what module_1.py must contain is:
Correct:
image_path = 'subpackage_1/photo.png'
cv2.imread(image_path)
Wrong:
image_path = 'photo.png'
cv2.imread(image_path)
although module_1.py and photo.png are at same directory.
├───root
│ ├───dir_a
│ │ ├───file_a.py
│ │ └───file_xx.py
│ ├───dir_b
│ │ ├───file_b.py
│ │ └───file_yy.py
│ ├───dir_c
│ └───dir_n
You can add the parent directory to PYTHONPATH, in order to achieve that, you can use OS depending path in the "module search path" which is listed in sys.path. So you can easily add the parent directory like following:
# file_b.py
import sys
sys.path.insert(0, '..')
from dir_a.file_a import func_name
This works for me on windows
# some_file.py on mainApp/app2
import sys
sys.path.insert(0, sys.path[0]+'\\app2')
import some_file
In my case I had a class to import. My file looked like this:
# /opt/path/to/code/log_helper.py
class LogHelper:
# stuff here
In my main file I included the code via:
import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper
I bumped into the same question several times, so I would like to share my solution.
Python Version: 3.X
The following solution is for someone who develops your application in Python version 3.X because Python 2 is not supported since Jan/1/2020.
Project Structure
In python 3, you don't need __init__.py in your project subdirectory due to the Implicit Namespace Packages. See Is init.py not required for packages in Python 3.3+
Project
├── main.py
├── .gitignore
|
├── a
| └── file_a.py
|
└── b
└── file_b.py
Problem Statement
In file_b.py, I would like to import a class A in file_a.py under the folder a.
Solutions
#1 A quick but dirty way
Without installing the package like you are currently developing a new project
Using the try catch to check if the errors. Code example:
import sys
try:
# The insertion index should be 1 because index 0 is this file
sys.path.insert(1, '/absolute/path/to/folder/a') # the type of path is string
# because the system path already have the absolute path to folder a
# so it can recognize file_a.py while searching
from file_a import A
except (ModuleNotFoundError, ImportError) as e:
print("{} fileure".format(type(e)))
else:
print("Import succeeded")
#2 Install your package
Once you installed your application (in this post, the tutorial of installation is not included)
You can simply
try:
from __future__ import absolute_import
# now it can reach class A of file_a.py in folder a
# by relative import
from ..a.file_a import A
except (ModuleNotFoundError, ImportError) as e:
print("{} fileure".format(type(e)))
else:
print("Import succeeded")
Happy coding!
I'm quite special : I use Python with Windows !
I just complete information : for both Windows and Linux, both relative and absolute path work into sys.path (I need relative paths because I use my scripts on the several PCs and under different main directories).
And when using Windows both \ and / can be used as separator for file names and of course you must double \ into Python strings,
some valid examples :
sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')
(note : I think that / is more convenient than \, event if it is less 'Windows-native' because it is Linux-compatible and simpler to write and copy to Windows explorer)
If the purpose of loading a module from a specific path is to assist you during the development of a custom module, you can create a symbolic link in the same folder of the test script that points to the root of the custom module. This module reference will take precedence over any other modules installed of the same name for any script run in that folder.
I tested this on Linux but it should work in any modern OS that supports symbolic links.
One advantage to this approach is that you can you can point to a module that's sitting in your own local SVC branch working copy which can greatly simplify the development cycle time and reduce failure modes of managing different versions of the module.
I was working on project a that I wanted users to install via pip install a with the following file list:
.
├── setup.py
├── MANIFEST.in
└── a
├── __init__.py
├── a.py
└── b
├── __init__.py
└── b.py
setup.py
from setuptools import setup
setup (
name='a',
version='0.0.1',
packages=['a'],
package_data={
'a': ['b/*'],
},
)
MANIFEST.in
recursive-include b *.*
a/init.py
from __future__ import absolute_import
from a.a import cats
import a.b
a/a.py
cats = 0
a/b/init.py
from __future__ import absolute_import
from a.b.b import dogs
a/b/b.py
dogs = 1
I installed the module by running the following from the directory with MANIFEST.in:
python setup.py install
Then, from a totally different location on my filesystem /moustache/armwrestle I was able to run:
import a
dir(a)
Which confirmed that a.cats indeed equalled 0 and a.b.dogs indeed equalled 1, as intended.
Instead of just doing an import ..., do this :
from <MySubFolder> import <MyFile>
MyFile is inside the MySubFolder.
In case anyone still looking for a solution. This worked for me.
Python adds the folder containing the script you launch to the PYTHONPATH, so if you run
python application/app2/some_folder/some_file.py
Only the folder application/app2/some_folder is added to the path (not the base dir that you're executing the command in). Instead, run your file as a module and add a __init__.py in your some_folder directory.
python -m application.app2.some_folder.some_file
This will add the base dir to the python path, and then classes will be accessible via a non-relative import.
The code below imports the Python script given by it's path, no matter where it is located, in a Python version-safe way:
def import_module_by_path(path):
name = os.path.splitext(os.path.basename(path))[0]
if sys.version_info[0] == 2:
# Python 2
import imp
return imp.load_source(name, path)
elif sys.version_info[:2] <= (3, 4):
# Python 3, version <= 3.4
from importlib.machinery import SourceFileLoader
return SourceFileLoader(name, path).load_module()
else:
# Python 3, after 3.4
import importlib.util
spec = importlib.util.spec_from_file_location(name, path)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
I found this in the codebase of psutils, at line 1042 in psutils.test.__init__.py (most recent commit as of 09.10.2020).
Usage example:
script = "/home/username/Documents/some_script.py"
some_module = import_module_by_path(script)
print(some_module.foo())
Important caveat: The module will be treated as top-level; any relative imports from parent packages in it will fail.
Wow, I did not expect to spend so much time on this. The following worked for me:
OS: Windows 10
Python: v3.10.0
Note: Since I am Python v3.10.0, I am not using __init__.py files, which did not work for me anyway.
application
├── app
│ └── folder
│ └── file.py
└── app2
└── some_folder
└── some_file.py
WY Hsu's 1st solution worked for me. I have reposted it with an absolute file reference for clarity:
import sys
sys.path.insert(1, 'C:\\Users\\<Your Username>\\application')
import app2.some_folder.some_file
some_file.hello_world()
Alternative Solution: However, this also worked for me:
import sys
sys.path.append( '.' )
import app2.some_folder.some_file
some_file.hello_world()
Although, I do not understand why it works. I thought the dot is a reference to the current directory. However, when printing out the paths to the current folder, the current directory is already listed at the top:
for path in sys.path:
print(path)
Hopefully, someone can provide clarity as to why this works in the comments. Nevertheless, I also hope it helps someone.
This problem may be due Pycharm
I had the same problem while using Pycharm. I had this project structure
skylake\
backend\
apps\
example.py
configuration\
settings.py
frontend\
...some_stuff
and code from configuration import settings in example.py raised import error
the problem was that when I opened Pycharm, it considered that skylake is root path and ran this code
sys.path.extend(['D:\\projects\\skylake', 'D:/projects/skylake'])
To fix this I just marked backend directory as source root
And it's fixed my problem
You can use importlib to import modules where you want to import a module from a folder using a string like so:
import importlib
scriptName = 'Snake'
script = importlib.import_module('Scripts\\.%s' % scriptName)
This example has a main.py which is the above code then a folder called Scripts and then you can call whatever you need from this folder by changing the scriptName variable. You can then use script to reference to this module. such as if I have a function called Hello() in the Snake module you can run this function by doing so:
script.Hello()
I have tested this in Python 3.6
I usually create a symlink to the module I want to import. The symlink makes sure Python interpreter can locate the module inside the current directory (the script you are importing the other module into); later on when your work is over, you can remove the symlink. Also, you should ignore symlinks in .gitignore, so that, you wouldn't accidentally commit symlinked modules to your repo. This approach lets you even successfully work with modules that are located parallel to the script you are executing.
ln -s ~/path/to/original/module/my_module ~/symlink/inside/the/destination/directory/my_module
If you have multiple folders and sub folders, you can always import any class or module from the main directory.
For example: Tree structure of the project
Project
├── main.py
├── .gitignore
|
├── src
├────model
| └── user_model.py
|────controller
└── user_controller.py
Now, if you want to import "UserModel" class from user_model.py in main.py file, you can do that using:
from src.model.user_model.py import UserModel
Also, you can import same class in user_controller.py file using same line:
from src.model.user_model.py import UserModel
Overall, you can give reference of main project directory to import classes and files in any python file inside Project directory.

How to import a package from a different directory in the same program?

Lets say I have a directory tree that looks like this:
main -
|
lib-
|
core-
|
fun-
|
some_file
stuff-
|
another_file
How could I import the modules from some_file into another_file? Everytime I try to do the importing (yes I know about __init__.py) I get an error:
Traceback (most recent call last):
File "file.py", line 6, in <module>
from some_file import some_method
ImportError: No module named some_file
Is it possible to import the modules into another file?
You can import using absolute or relative imports if all the directories that you're traversing are Python packages (with __init__.py file in them).
Assuming that you are running your program from the directory in which main package is, you'd import some_file module with:
import main.lib.core.fun.some_file
Otherwise you have to append to Python path before attempting import:
import sys
sys.path.append("......main/lib/core")
import fun.some_file
The second example assumes that fun is a Python package with __init__.py file in it.
Just add an __init__.py file to the directory to make it be seen as a module:
main -
|
lib-
|
core-
|
fun-
|
some_file
__init__.py
stuff-
|
another_file
The __init__.py can be a blank file, all that matters is that it exists. Then, you can do import fun.some_file

Python imports with __init__.py

No matter how I structure the imports in the code files and in the __init__.py files, I can't seem to get it right for executing the program and running the tests using pytest. How do I need to write the imports when my project structure looks like this:
src/
__init__.py
VocableFileWriter.py
WordListHelper.py
WordListReader.py
XLDAttributeValueAdder.py
exceptions/
__init__.py
XMLInvalidException.py
XMLParseException.py
gui/
__init__.py
GTKSignal.py
XLDAttributeValueAdderWindow.py
test/
__init__.py
test_XLDAttributeValueAdder.py
xmlparser/
__init__.py
XMLParser.py
Currently I have them like this:
In the __init__.py files I have the imports like this (src/__init__.py):
from src import *
from src.exceptions import *
from src.xmlparser import *
and in a subpackage (src/xmlparser/__init__.py):
from src.xmlparser import *
So I guess those are project-absolute paths to the modules.
In the code files themselves I import like this:
import os
import sys
from VocableFileWriter import VocableFileWriter
from XLDAttributeValueAdder import XLDAttributeValueAdder
However, when I execute the code from the directory above src using:
./src/main.py
It tells me that:
Traceback (most recent call last):
File "./src/main.py", line 6, in <module>
from VocableFileWriter import VocableFileWriter
File "/home/xiaolong/Development/PycharmProjects/xld-attribute-value-adder/src/VocableFileWriter.py", line 2, in <module>
from XMLInvalidException import XMLInvalidException
ImportError: No module named 'XMLInvalidException'
It used to be a PyCharm project, but I couldn't get it to run with the imports structure PyCharm used when not using PyCharm but running it from the terminal, so I decided I wanted to take the whole import stuff into my own hands. So don't get confused by it being in a PyCharm directory.
I also want to be able to execute the tests using for example:
py.test src/test/test_XLDAttributeValueAdder.py
How do I solve this mess?
Edit#1:
I had the program running once, but then the test complained about missing modules, probably because it's in another subdirectory and I tried so many configurations, that I don't know how I had the program running anymore. If possible please add some explanation why a certain structure is correct and works for both, tests and the program itself.
EDIT#2:
I've managed to get the tests running now, but now the program doesn't run anymore.
I emptied all the __init__.py files and used only project-absolute paths in the code files like this (src/test/test_XLDAttributeValueAdder.py):
from src.VocableFileWriter import VocableFileWriter
from src.WordListHelper import WordListHelper
from src.WordListReader import WordListReader
from src.XLDAttributeValueAdder import XLDAttributeValueAdder
from src.exceptions.XMLInvalidException import XMLInvalidException
from src.exceptions.XMLParseException import XMLParserException
from src.xmlparser.XMLParser import XMLParser
from src.test.path_helper import go_up
from src.test.path_helper import go_in
and in the main.py:
from src.VocableFileWriter import VocableFileWriter
from src.XLDAttributeValueAdder import XLDAttributeValueAdder
the output of ./src/main.py:
./src/main.py
Traceback (most recent call last):
File "./src/main.py", line 6, in <module>
from src.VocableFileWriter import VocableFileWriter
ImportError: No module named 'src'
EDIT#3:
I've tried the relative import way like this:
main.py moved one directory up
The structure now looks like this:
main.py
src/
__init__.py
VocableFileWriter.py
WordListHelper.py
WordListReader.py
XLDAttributeValueAdder.py
exceptions/
__init__.py
XMLInvalidException.py
XMLParseException.py
gui/
__init__.py
GTKSignal.py
XLDAttributeValueAdderWindow.py
test/
__init__.py
test_XLDAttributeValueAdder.py
xmlparser/
__init__.py
XMLParser.py
__init__.py files empty
main.py file gets relative
Imports look like this:
import os
import sys
from .src.VocableFileWriter import VocableFileWriter
from .src.XLDAttributeValueAdder import XLDAttributeValueAdder
When I try to run the main.py file:
Traceback (most recent call last):
File "main.py", line 6, in <module>
from .src.VocableFileWriter import VocableFileWriter
SystemError: Parent module '' not loaded, cannot perform relative import
However, there is a __init__.py file in the same directory as the main.py file, also empty.
You'd better use relative imports.
When doing from src import * in src/__init__.py you'll only import anything you've defined before calling the import. Most likely that's just nothing. If you've defined the __all__ variable, you'll get the submodule from it, but maybe also an AttributeError if a variable hasn't been defined yet.
So instead import the modules you need explicitly where you need them like
from .VocableFileWriter import VocableFileWriter
from .exceptions.XMLInvalidException import XMLInvalidException
or lets say within src/gui/GTKSignal.py
from ..exceptions.XMLInvalidException import XMLInvalidException
Also you could use project-absolute paths like mentioned in your Edit#2.
Furthermore you've a problem with your path when calling ./src/main.py. In this case the directory containing src is not in the path. Instead ./src/ is in the path. Therefore python doesn't consider it a package anymore and since there's no other package with that name available, the import fails.
Instead put your main.py module in the same directory like the src package or call it as a module with python -m src.main. Doing so you could also rename it to src/main.py and call the package instad with python -m src.
When using the first approach, main should use an absolute import structure. Just think of it as a module you put anywhere on your computer, while your src package is somewhere else, where it can be found by Python, like any other module or package installed by the system. It's not different, when it's located besides the package itself, since the current directory is in sys.path.
main.py
import os
import sys
from src.VocableFileWriter import VocableFileWriter
from src.XLDAttributeValueAdder import XLDAttributeValueAdder

Python import doesn't work when file is imported

I am having difficulties to understand how the python importer works..
I have a python script (fractalDimension.py) that imports a submodule ("greedyColoring.py") using:
from boxCovering.greedyColoring import *
It works fine when I call it directly:
python fractalDimension.py
The problem began when I moved the script to a folder and added a main script which imports the fractalDimension.py because now the import of the boxCovering sub module doesn't work.
In the main script I call the fractalDimension method:
import fractality.fractalDimension as fd
fd.calculate()
but when I run
python main.py
I get the following error
Traceback (most recent call last):
File "main.py", line 5, in <module>
import fractality.fractalDimension as fd
File "fractalDimension.py", line 11, in <module>
from boxCovering.greedyColoring import *
ImportError: No module named 'boxCovering'
Directory layout:
main.py
fractalDimension/
|
+-- __init__.py
+-- fractalDimension.py
+-- boxCovering/
|
+-- __init__.py
+-- greedyColoring.py
Both init files are empty
Why python cannot find the boxCovering module?
The error is due to the fact that python is searching for a top-level package called boxCovering inside the PYTHONPATH and none exists (you have only a sub-package inside the current directory, but this isn't searched).
When you want to import a subpackage/submodule you want to use a(n explicit) relative import:
from .boxCovering.greedyColoring import *
note the . (dot) at the beginning.
Alternatively use the absolute import:
from fractality.fractalDimension.boxCovering.greedyColoring import *
In python2 the import allowed an implicit relative import, which is what you are trying to do. In that case the import:
from boxCovering import X
done in the way you are doing could have two different meanings:
import of the subpackage boxCovering of the fractalDimension package
import of the top-level package boxCovering
In python3 (see the What's new? and relevant PEP 0328) they decided that such an import always has the second meaning. If you want a relative import you have to explicitly state so by using the relative syntax, which uses a dot at the beginning of the module name.
Each dot means go to one directory above so . means the current directory while .. means the parent directory (as in unix paths) etc.
You can enable this semantics on python2 adding:
from __future__ import absolute_import
at the top of your files.

Categories