2

I am having an import problem. What I am trying to do is to import 2 functions with the same name from modules with the same name. Note that i am doing this in Pycharm.

I have the following directory structure:

test_import 
|--foo.py  
|--main.py  
|--test
   |--foo.py  

Code

foo.py in the test_import folder looks like:

def print_arg(x):
    print('print 1: {}'.format(x))

foo.py in the test folder looks like:

def print_arg(x):
    print('print 2: {}'.format(x))

Here is my code in main.py in which I am doing the imports of print_arg:

import sys
from foo import print_arg as print_arg
print_arg(1)
sys.path.insert(1, './test')
from foo import print_arg as print_arg_2
print_arg(1)
print_arg_2(1)

I expect this to print

print 1: 1
print 1: 1
print 2: 1

But it prints

print 1: 1
print 1: 1
print 1: 1

Somehow the second import does not work and print_arg_2 becomes a reference to print_arg. This is illustrated by doing the imports the other way around:

sys.path.insert(1, './test')
from foo import print_arg as print_arg_2
print_arg_2(1)
sys.path.pop(1)
from foo import print_arg
print_arg(1)
print_arg(1)
print_arg_2(1)

which prints:

print 2: 1
print 2: 1
print 2: 1

Changing the function name in test/foo.py to print_arg_2 does not work, it results in an error. It seems like a reference to foo.py in the project folder has been created and it tries to import from there instead of looking in other directories on sys.path

Traceback (most recent call last):
  File "C:\Users\jeroe\AppData\Local\Programs\Python\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-10fe80aec78f>", line 5, in <module>
    from foo import print_arg_2 as print_arg_2
ImportError: cannot import name 'print_arg_2' from 'foo' (C:\Users\jeroe\PycharmProjects\test_import\foo.py)

Changing the filename of foo.py in the test folder to e.g. foo2.py does work. However I prefer not to change the filename.

So I have 2 questions:

  1. Can somebody explain me what is going on here?

  2. What is a better way to import these 2 functions without having to change the file (module) name?

JvdB
  • 83
  • 7
  • You're importing from the same file twice. In your first code snippet, change the second import statement to `from test.foo import print_arg as print_arg_2`. Python import paths reflect the names of the directories the files are in. – Boris Verkhovskiy Feb 05 '20 at 10:26
  • 1
    try `from test.foo import print_arg as print_arg_2` – zamir Feb 05 '20 at 10:27

1 Answers1

2

First of all, you have to add an empty __init__.py file inside the test folder, so the second foo file can be imported.

Secondly, you have to write the full relative path to the second file when importing it. Right now, you are importing both times the first foo file.

Just modify the second import line to:

from test.foo import print_arg as print_arg_2
Jalo
  • 1,131
  • 1
  • 12
  • 28
  • Thank you for the answer. I woud appreciate if you could explain to me why importing the module separately worked (without the `__init__.py` file in the test folder) like this: `import sys` `sys.path.insert(1, './test')` `from foo import print_arg as print_arg_2` `print_arg_2(1)` – JvdB Feb 05 '20 at 11:09
  • 1
    in that case you are adding the directory _test_ to your path, which means that you can import modules directly from it. This is not a recommended way for importing nested packages, since you can easily create naming conflicts, and is a more obscure solution. More info about `sys.path.insert` [here](https://stackoverflow.com/questions/31291608/effect-of-using-sys-path-insert0-path-and-sys-pathappend-when-loading-modul). Actually, you are creating a name conflict in the case you mentioned, since the imported functions have the same name – Jalo Feb 05 '20 at 16:07