I've found myself in an import error situation I thought I was well past. I'm running Python 3.7.4 in VSCode on Windows 10. Without any further ado.. this is my folder and file structure, starting with folder crypto_code:
/crypto_code:
__init__.py (blank)
/crypto_driver:
__init__.py (blank)
crypto_balances.py
/crypto_exchg:
__init__.py (blank)
exchg_lens.py
bittrex_lens.py
coinbase_lens.py
Top of file coinbase_lens.py:
import exchg_lens
Top of file crypto_balances.py:
import sys
sys.path.append('..')
from crypto_exchg import coinbase_lens
Running coinbase_lens as main imports exchg_lens without error.
Running crypto_balances.py seems to recognize the paths/structure, but throws 'ModuleNotFoundError': No module named 'exchg_lens'.
Any help would be greatly appreciated. Thanks in advance.
This is an issue I've found troublesome as well. I have a setup that works and avoid messing with it. However this is good practice (for me) so ...
As a starting position I suggest abandoning import sys
and sys.path.append
. These are hacks that obscure the issue. If you use a linter (flake8 is what I use) then it will complain about sys.path.append
appearing before imports
and it is worth respecting what the linter dislikes.
I think the starting issue is, are you writing a module or a program. Restructuring your folders to provide a clear distinction.
/
program.py
/crypto
__init__.py (empty)
/driver
__init__.py (empty)
crypto_balances.py
/exchg
__init__.py (empty)
coinbase_lens.py
exchg_lens.py
/test
__init__.py (empty)
test_coinbase_lens.py
program.py
from crypto.driver import crypto_balances
from crypto.exchg import coinbase_lens, exchg_lens
crypto_balances.py
from ..exchg import coinbase_lens
print('crypto_balances')
coinbase_lens.py
from . import exchg_lens
print('coinbase_lens')
exchg_lens.py
print('exchg_lens')
When run from the / folder produces
python .\program.py
exchg_lens
coinbase_lens
crypto_balances
Of course you should have a test framework to run tests on your module. The test file has the following content. Pytest sucessfully finds (and runs) the following test.
from crypto.exchg import coinbase_lens
def test():
assert True
Later ... you can look at the package __init__.py
and adding the imports and __all__
there to allow namespace management. Easy enough to add later.
Feels like I am missing a useful point that is worth including. \crypto\__init__.py
and program.py
can be altered to allow you to manage how the namespace of the module appears to the program.
__init__.py
becomes
from crypto.driver import crypto_balances
from crypto.exchg import coinbase_lens, exchg_lens
__all__ = [
"crypto_balances",
"coinbase_lens", "exchg_lens"
]
program.py is now ...
from crypto import crypto_balances
from crypto import coinbase_lens, exchg_lens