andrew-94
andrew-94

Reputation: 27

Relative import between modules

I've written a group of functions that I wanted to use for my computation and I've organize them in some .py file, say functions1.py and functions2.py. Within the same folder I have also another file main.py, then:

root\ 
- functions1.py
- functions2.py 
- main.py

Inside functions1.py suppose I have the following code:

import numpy as np

def mycos(x): 
    return np.cos(x)

def mysin(x):
    return np.sin(x)

While inside functions2.py:

from .functions1 import mysin, mycos

def mytan(x):
    return mysin(x)/mycos(x)

Now suppose that main.py contain:

import numpy as np
from .functions2 import mytan

angle = np.pi/3
if mytan(angle) == np.tan(angle):
    print('OK')

Then, If I execute main.py I got the following error:

Traceback (most recent call last):
  File "functions2.py", line 6, in <module>
    from .functions1 import mysin, mycos
ImportError: attempted relative import with no known parent package

Did I miss something in the use of relative import?

Upvotes: 1

Views: 108

Answers (2)

Mr_and_Mrs_D
Mr_and_Mrs_D

Reputation: 34046

What os.chdir(os.path.dirname(os.path.abspath(__file__))) suggested above does is changing the working directory to the parent folder of the main.py. This looks messy and can fail in subtle ways (relative paths is one). The correct solution is to run the main.py using the -m switch from root's parent directory. This is actually the recommended way of running python scripts. So you should run:

$ python -m root.main # from parent dir of root

Then module main is run as part of root package (which is the parent package missing in your case)

Note this will still work if you create a (sub) package (root.) functions, as suggested above - adding an __init__.py should not be needed with latest py3 still it's a good idea to add it for clarity.

Upvotes: 1

Giuppox
Giuppox

Reputation: 1629

i think this is because when you run the code you are not executing in the project directory, try adding these few lines at the beginning of the code of main.py

import os # don't add this line if you have already imported os
os.chdir(os.path.dirname(os.path.abspath(__file__)))

let me know if this works, if it doesn't... can you share the full code to understand better your problem?


EDIT
the problem should be that the file functions1.py and functions2.py are not actually modules, to fix this i am gonna suggest you two solutions:

Create a folder

as the two function file are not taken as a module, create a folder and put them inside it like so

MAINDIR
– main.py
– functions
–– functions1.py
–– functions2.py

the code is this

main.py

import numpy as np
from functions.functions2 import mytan

angle = np.pi/3
if mytan(angle) == np.tan(angle):
    print('OK')

functions1.py

import numpy as np

def mycos(x):
    return np.cos(x)

def mysin(x):
    return np.sin(x)

functions2.py

from .functions1 import mysin, mycos

def mytan(x):
    return mysin(x)/mycos(x)

Use __init__.py


MAINDIR
– main.py
– functions
–– __init__.py
–– functions1.py
–– functions2.py

and this is the code

init.py

import functions1, functions2

(and all other files just like the first solution)
note that this solution is a bit longer, but this should be the most "correct" way to do this

And then?

if you wanna understand better why it wasn't working i would like to suggest you to read this well done articles:
real python
geeks for geeks

Cheers J.Bloom

Upvotes: 2

Related Questions