balkon16
balkon16

Reputation: 1448

PyCharm import vs interpreter

There is the following PyCharm project structure:

testImport
    target
        __init__.py
        script_1.py
        script_2.py

The contents are following:

#script_1.py
import datetime

now_ts = datetime.datetime.now()
#script_2.py
from script_1 import now_ts

print('Now: {}'.format(now_ts))

PyCharm requires me to correct the import line in the script_2.py file and use from target.script_1 import now_ts. Once I try to execute ~/testImport: ./target/script_2.py I get ModuleNotFoundError: No module named 'target'. How is it possible that PyCharm suggests incorrect solution or is there something going on that I don't know about?

Upvotes: 0

Views: 77

Answers (2)

Hieast
Hieast

Reputation: 87

The key point is that when your run your script in the default way python ./target/script_2.py, the interpreter considered script_2 as main module and won't let you find upper folder.

You can run in the following ways to aviod ModuleNotFoundError (only if you clearly understand what you are doing, don't use in large project):

  1. in ~/testImport run python -m target.script_2
  2. script_2.py add in the top
__package__ = "target.script_2"
  1. script_2.py add in the top
if __name__ == "__main__":
    import sys
    import os
    sys.path.insert(0, os.path.abspath(os.curdir))

in ~/testImport and run python ./target/script_2.py

I would be very appreciate if anyone could help me correct my unnatural english.

Upvotes: 1

Lescurel
Lescurel

Reputation: 11651

The PyCharm suggestion is probably because the IDE consider that your target folder is a module. Having an executable script in a module is considered an anti pattern. See Guido Van Rossum opinion about it.

I'm -1 on this and on any other proposed twiddlings of the main machinery. The only use case seems to be running scripts that happen to be living inside a module's directory, which I've always seen as an antipattern. To make me change my mind you'd have to convince me that it isn't.

I suggest that you change the structure of your project to make your main logic in a module, and the executable outside of the module, i.e:

testImport
├── script_1.py
└── target
    └── my_logic.py

And in your script_1.py :

from target.my_logic import now_ts

Note: Of course, I am just using a call to authority as an argument here. With your use case, it might be better to continue the way you are developing. In that case, just dismiss the IDE suggestion.

Upvotes: 2

Related Questions