0

I have a directory which contains a bunch of function and another folder which contains my main project which I would like to be able to run from the terminal: kf_sine_demo.py.

enter image description here

When I run line by line the code from VS-Code (using Shift+Enter), everything works fine. In particular I can import the functions for further use:

from EKFUKF_Py import lti_disc, kf_predict, kf_update, rts_smooth

However, when I run the file from the terminal:

python kf_sine_demo.py

I get the following error:

Traceback (most recent call last):
  File "EKFUKF_Py/demo/kf_sine_demo/kf_sine_demo.py", line 16, in <module>
    from EKFUKF_Py import lti_disc, kf_predict, kf_update, rts_smooth
ModuleNotFoundError: No module named 'EKFUKF_Py'

I see solutions which include specifying the full path. I have strong preference for relative imports.


UPDATE:

This solution has been most useful to me: https://stackoverflow.com/a/37193862/4576194.

  • Run python -m EKFUKF_Py.demo.kf_sine_demo.kf_sine_demo form the parent directory of EKFUKF_Py

But, that's not quite what I want. I want to be able to run python kf_sine_demo.py from kf_sine_demo directory and I want it to know that the functions it needs to import are located 2 levels up.

Sandu Ursu
  • 1,181
  • 1
  • 18
  • 28
  • I've tried execution from the `EKFUKF_Py` directory without any luck. – Sandu Ursu Oct 03 '19 at 23:07
  • Exception messages? That does not work either : `File "demo/kf_sine_demo/kf_sine_demo.py", line 16, in from . import lti_disc, kf_predict, kf_update, rts_smooth ImportError: cannot import name 'lti_disc' from '__main__' (demo/kf_sine_demo/kf_sine_demo.py)` – Sandu Ursu Oct 03 '19 at 23:16
  • 1
    If you need to have access to files from two parent folders up, you could append them to the path variable: `sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir))` – RoyM Oct 04 '19 at 00:16
  • I guess it works in VS-Code because I've added `EKFUKF_Py` as a working directory. @RoyM that is not the same as doing a relative import, is it? Is there any way to just tell it to look for the files 2 levels up, irrespective of the location it is in? – Sandu Ursu Oct 04 '19 at 11:56
  • The solution I provided would do just that, @Sandu Ursu. To clarify, the line inserts into the path-variable two parent folders up from wherever the running script is located, i.e. relative pathing. – RoyM Oct 04 '19 at 12:57
  • I get an error when I include your line above the `from EKFUKF_Py import lti_disc, kf_predict, kf_update, rts_smooth` and execute the file: `ModuleNotFoundError: No module named 'EKFUKF_Py'` – Sandu Ursu Oct 04 '19 at 13:04
  • I think that is because I use another import in one of the files from the `EKFUKF_Py` directory. – Sandu Ursu Oct 04 '19 at 13:25
  • 1
    Using my line you're adding the directory EKFUNKF_Py to your path-variable. Having that, you can import functions from each file as follows: `from lti_disc import *` etc. EKFUKF_py is not a module in this context, that might be why you're given an error. If your files recursively tries to import each other, this work around will not work for you. You should then probably look at configuring a `__init__.py`-file as olinox suggests. Or call the execution of the file from an apropriate place to begin with. – RoyM Oct 04 '19 at 15:28
  • Scratch that, it should still work, as the path-variable stays for the entire duration of your program and for all subsequent calls. – RoyM Oct 04 '19 at 15:45

1 Answers1

1

You have to understand how python path works. This is a list of directories where python looks for the modules you try to import, you can display it uing the sys.path command. There are a bunch of directories that python automatically add to, like path\to\your_python_install\lib, and python also add the working directory when you run a script.

This means that when you do:

python kf_sine_demo.py

The parent directory of this file (kf_sine_demo) is added to the path, but the EKFUKF_Py is not. Thus python can not find the modules in it.

From here, two solutions. Either you manually add this directory (which I find a little ugly, but it works):

sys.path.append("path/to/EKFUKF_Py")

Or you ensure to always run your files from the main directory, through a main.py file, for example. from there, you will be able to call every submodule in this directory.

More here: https://www.devdungeon.com/content/python-import-syspath-and-pythonpath-tutorial

olinox14
  • 6,177
  • 2
  • 22
  • 39
  • So, if I have a few demos which I want to run, you would suggest me to pass an argument to the `main.py` with the name of the demo I'm interested in? – Sandu Ursu Oct 04 '19 at 13:13
  • 1
    For example yes, but if it is not a production app and if it is just for testing purpose, you could easily go with the first solution, and add the `sys.path.append` line to the `__init__.py` file inside the kf_sine_demo directory or at the beginning of your script. You may also replace your `from EKFUKF_Py import ...` line by something like `try: from EKFUKF_Py import ...; except ImportError: sys.path.append(...); from EKFUKF_Py import ...;` (replacing the semicolons here by newlines, of course) – olinox14 Oct 04 '19 at 13:33