3

I have a folder structure for a Python project as follows:

proj/
├── cars
│   ├── honda.py
│   └── volvo.py
├── trucks
│   ├── chevy.py
│   └── ford.py
├── main.py
└── params.py

Contents of params.py:

""" Parameters used by other files. """

serial = '12-411-7843'

Contents of honda.py:

""" Information about Honda car. """

from params import serial

year = 1988
s = serial

print('year is', year)
print('serial is', s)

From within the proj/ folder I can run scripts using iPython:

$ cd path/to/proj/
$ ipython

In [1]: run cars/honda.py
year is 1988
serial is 12-411-7843

If I try to run the script using the python command, I get a module not found error for params.py:

$ cd path/to/proj/
$ python cars/honda.py
Traceback (most recent call last):
  File "cars/honda.py", line 5, in <module>
    from params import serial
ModuleNotFoundError: No module named 'params'

Why doesn't the approach using the python command work?

NOTE - The examples above are executed on a Mac using the Anaconda Python distribution. There is a similar question about an import issue when running on Windows vs Linux machines. However, my question is related to using iPython vs python on the Mac to run scripts.

wigging
  • 8,492
  • 12
  • 75
  • 117
  • Possible duplicate of [ImportError: No module named ](https://stackoverflow.com/questions/43476403/importerror-no-module-named-something) – GetHacked Jul 27 '18 at 14:33
  • @Dyno I edited my question to explain the difference from the possible duplicate question. – wigging Jul 27 '18 at 14:57
  • @wigging does my solution below work for you? If not, can you say why not? – duhaime Jul 27 '18 at 15:08
  • @wigging Thanks, I totally missed that distinction & the current answers all seemed to be using the same train of thought. Hopefully your edit will help find a solution. – GetHacked Jul 27 '18 at 15:17

3 Answers3

7

Above from params import serial insert:

import sys
[sys.path.append(i) for i in ['.', '..']]

This will add your current working directory and its parent directory to the list of locations from which you can import.

Handling imports when running script from a parent directory of proj

If you want to be able to import params into cars/honda.py when running your script from directories that are parents of project, you can use the following:

import sys
import os
from functools import reduce

# allow imports when running script from within project dir
[sys.path.append(i) for i in ['.', '..']]

# allow imports when running script from project dir parent dirs
l = []
script_path = os.path.split(sys.argv[0])
for i in range(len(script_path)):
  sys.path.append( reduce(os.path.join, script_path[:i+1]) )
duhaime
  • 25,611
  • 17
  • 169
  • 224
  • This works from within the `proj/` folder. Is there a way to make it work relative to the path of the script that is run? – wigging Jul 27 '18 at 15:27
  • @wigging I updated my response to handle the case where you run the script from a parent directory of `proj/` does this help? In general, just use `sys.path.append()` to add to the list of paths from which you can import resources... – duhaime Jul 27 '18 at 20:27
  • So why is iPython able to find the files but the `python` command requires defining the path? – wigging Jul 29 '18 at 02:49
  • @wigging where did you start the ipython server, and did you modify your path before, while, or since using ipython? – duhaime Aug 01 '18 at 14:00
  • I started the iPython REPL (not Jupyter Notebook) from within the `proj/` folder. With iPython, I did not have to modify the path, everything ran fine. – wigging Aug 01 '18 at 14:18
  • @wigging if this is the case after a restart, try printing (sys.path) from both iPython and Python. You should see they're different. Any number of things may have influenced either path -- these details are specific to your setup on your machine. Do be aware that iPython / Jupyter cache imports, so if you modified your path and imported inside iPython, that import may remain available to you even if you remove the path modification code. I hope this helps. – duhaime Aug 08 '18 at 12:11
  • 1
    this is a star-worthy post :) – roberto tomás May 15 '21 at 12:17
0

If you want imports to be referenced of the base proj directory you must set the PYTHONPATH to that directory. Currently honda.py is looking around for a moudule called params inside it's own module.

~$ cd path/to/project
~$ PYTHONPATH=$(pwd)

Alternatively you could use relative imports.

modesitt
  • 7,052
  • 2
  • 34
  • 64
0

The problem of location,you should write full path for the params.py. Ipython has a character that can use linux command .so first you cd the directory,the interpreter can find the params.py. But the command python need full path of the params.py. So that is the reason you cannot run the processing.