two py file:
./src/foo.py
def bar ():
print 'bar!'
./tests/testfoo.py
from foo import bar
print 'testing'
bar ()
in the root folder './', calling
python ./tests/testfoo.py
the result is
Traceback (most recent call last):
File "./tests/testfoo.py", line 1, in <module>
from foo import bar
ImportError: No module named foo
running the testfoo.py but naturally module foo could not be found by the interpreter. can i give any parameter to interpreter to lookup modules in the folder 'src'?
Edit #1
also added two empty init.py file.
./src/__init__.py
./tests/__init__.py
still getting the same error.
Edit #2 (Solution)
I solved problem by adding a new initialization py file
prep.py
import os, sys
cur = os.path.dirname (__file__)
pathtest = os.path.join (cur, 'tests')
sys.path.append (pathtest)
then called:
python prep.py tests/testfoo.py
it worked
Try this:
import sys
sys.path.append('your/path')
import testfoo
You may need to make ./tests an absolute path...
The environment variable PYTHONPATH keeps the search paths for Python modules. For example
$ echo $PYTHONPATH
/home/username/lib/python2.6/site-packages:/usr/local/stsci_python/lib/python:
Modify this to add your directory:
export PYTHONPATH="$PYTHONPATH:/your/new/path"
(This is on BASH, by the way.)
Put a __init__.py in those directories to indicate to python that they should be treated like packages.
./src/__init__.py
./tests/__init__.py
This will fix the issue from the location you are running it, since python will check the current directory. But it will not fix the issue if you were to run it from some random location like:
/some/other/path/ $ /projects/tests/testfoo.py
What you need is to modify your PYTHONPATH to include that location:
PYTHONPATH=$PYTHONPATH:/projects
This can be added to either your shell environment, or done manually each time.
Related
I have a certain project structure:
- azima
- .vscode
- core
- project_setup.py
- helper
- log_helper
- venv
In project_setup.py:
import os
import json
import numpy as np
import pandas as pd
import random
from helper.log_helper import log
if __name__ == "__main__":
print('hello world')
Running this file in terminal:
(venv) rmali#rakeshmali:~/git/azima$ /home/rmali/git/azima/venv/bin/python /home/rmali/git/azima/core/project_setup.py
Traceback (most recent call last):
File "/home/rmali/git/azima/core/project_setup.py", line 6, in <module>
from helper.log_helper import log
ModuleNotFoundError: No module named 'helper'
I get this error. What am I doing wrong? Am I missing something?
But running like this python -m core.project_setup works.
Reason:
The path of folder azima does not in the sys.path(PYTHONPATH).
Solution:
You can do this to modify the PYTHONPATH:
Add these in the settings.json file to Modify the PYTHONPATH in the terminal:
"terminal.integrated.env.windows": {
"PYTHONPATH": "xxx/site-packages"
}
Create a .env file under your workspace, and add these settings in it to modify the PYTHONPATH for the extension and debugger:
PYTHONPATH=xxx/site-packages
You can refer to here to understand the effects of these two configurations.
Modify it directly in the python file. Add these codes in the b.py file.
import sys; sys.path.append("xxx/Project/src")
The reason that running
(venv) rmali#rakeshmali:~/git/azima$ python ./core/project_setup.py
fails while
(venv) rmali#rakeshmali:~/git/azima$ python -m core.project_setup
succeeds is that when running python -m <module-name, Python adds the current directory to the start of sys.path, which allows modules in that directory such as helper to be imported as top level modules, i.e. with import helper. Running python <script> does not add the current directory to the start of sys.path. Instead, Python adds the directory containing the script to the start of sys.path.
Here are the relevant sections of the docs.
The -m switch
As with the -c option, the current directory will be added to the start of sys.path.
and the docs for the -c option add
the current directory will be added to the start of sys.path (allowing modules in that directory to be imported as top level modules)
Docs for python <script>
If the script name refers directly to a Python file, the directory containing that file is added to the start of sys.path, and the file is executed as the __main__ module.
If the script name refers to a directory or zipfile, the script name is added to the start of sys.path and the __main__.py file in that location is executed as the __main__ module.
When I try to $> python ./tools/test.py I get an import error that I cannot import a module that exists in the directory from which I am invoking python. However, I can import this module, $> python -c "import mod" works.
I'm relying on the fact that ./ is (in effect) on the PYTHONPATH.
What is python doing to the python path when I run the interpreter on a script that exists in a different directory? Is there a way to "lock" the current working directory so that I can get the import to work?
My setup:
./mod.py :
x = 5 # just for demonstration purposes
./tools/test.py :
from mod import x
# ... snip ... actual content
I am invoking python from the directory that contains mod.py and tools/:
$> python -c "from mod import x" # works fine
$> python tools/test.py
Traceback (most recent call last):
File "tools/test.py", line 1, in <module>
from mod import x
ModuleNotFoundError: No module named 'mod'
Note that the current directory, which contains mod.py and tools is not on my PYTHONPATH.
I'm relying on the fact that ./ is (in effect) on the PYTHONPATH.
It's not. It's not on PYTHONPATH, and it's not on sys.path. When you run a script by file path, it's the script's directory that gets added to sys.path. You can see what gets added to sys.path for each way of specifying a program to run in the Python command line docs.
I have the following directory structure, in Ubuntu:
/Test/Foo
/Test/Foo/foo.py
If I am in /Test, and I run python from the command line, followed by from Foo import foo, I get the following error: ImportError: No module named Foo.
But this is very confusing, since according to here, one of the directories used to search when importing is the directory from which the script was invoked. If I print out sys.path though, it does not include /Test, it just includes other standard Python directories.
Any idea what is going on?
If I'm getting you right, what you are trying to achieve here is the Foo to be a package and foo be a module.
Since Foo is not made into a package (You don't have __init__.py in the directory), it is not recognized as a package and thus not imported.
When you move into /Test/Foo, then you are simply importing the module foo, which will work.
What you possibly need to do here is to create an __init__.py file inside /Test/Foo and then import the module from the package.
Or you can try relative imports. Something like from .Foo import foo.
If you just need a function try this (python 2.7):
sys.path.insert() inserts the directory specified in the path python uses to find files.
commify.py is a file in subdirectory xyz that contains a function commify(value)
import os
import sys
sys.path.insert(0, os.getcwd() + r'\xyz')
from commify import commify
print commify(12345678)
output: 12,345,678
I have the following directory structure
project/
bin/
script
stuff/
__init__.py
mainfile.py
Inside of script, I have the following to enable command line execution:
#!/usr/bin/env python
from stuff import mainfile
This works, but I would have expected needing to jump up one level...
from ..stuff import mainfile
or
from project.stuff import mainfile
What am I missing here?
Actually none of your examples should work out of the box.
Let's modify bin/script.py somewhat:
#! /usr/bin/env python
import sys
print sys.path
from stuff import mainfile
This should yield something like
['.../project/bin', ...]
Traceback (most recent call last):
File "bin/script.py", line 6, in <module>
from stuff import mainfile
ImportError: No module named stuff
Only the directory of the script (not the current directory) is added to sys.path automatically:
As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter.* If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.
Hence there's no stuff module on sys.path. I'm not sure about your environment setup, but this is the canonical result when no additional parameters are set up (e.g. PYTHONPATH).
Similarily,
from ..stuff import mainfile
will result in the classic ValueError: Attempted relative import in non-package. You are informed of the fact that you can only do relative imports relative to actual modules. Since inside script .. does not refer to a module (because the script itself is the top level module so to say), a relative import does not work here. In a manner of speaking from Python's perspective, there is no module above the script and thus .. does not refer to something tangible when used in the context of the script.
Note that this also means that it does not help to only make project and project/bin into modules themselves by dropping __init__.py marker files. Relative imports to a parent of the script are only possible if the parent of the script is actually something python has a concept of.
This is one of the reasons, why the -m command line switch exists making it possible to run a module from the command line. For example, given the above relative import
python -m project.bin.script
does the trick, but only if executed from the proper directory (projectdir/..).
That problem is even worse with
from project.stuff import mainfile
because the project directory is only automatically on sys.path when you start a script from the directory above project and do not specify a main script to run:
cd <projectdir>/..
python -m project.bin.script
# works
cd <projectdir>
python -m bin.script
# does not work, because `sys.path` starts with <projectdir>
# and it's `stuff.mainfile` now, not `project.stuff.mainfile`.
If you want to import modules from project in your script, fix up sys.path to your needs:
import sys
import os
sys.path.insert(0, os.path.dirname(sys.path[0]))
from stuff import mainfile
You need to first add the parent directory into sys.path. Try the following:
# This is a file in bin/ directory.
this_file_path = os.path.dirname(__file__)
sys.path.append(os.path.join(this_file_path, '..'))
import stuff.mainfile
What is the correct way to fix this ImportError error?
I have the following directory structure:
/home/bodacydo
/home/bodacydo/work
/home/bodacydo/work/project
/home/bodacydo/work/project/programs
/home/bodacydo/work/project/foo
And I am in the directory
/home/bodacydo/work/project
Now if I type
python ./programs/my_python_program.py
I instantly get
ImportError: No module named foo.tasks
The ./programs/my_python_program.py contains the following line:
from foo.tasks import my_function
I can't understand why python won't find ./foo/tasks.py - it's there.
If I do it from the Python shell, then it works:
python
>>> from foo.tasks import my_function
It only doesn't work if I call it via python ./programs/my_python_program.py script.
Python does not add the current directory to sys.path, but rather the directory that the script is in. Add /home/bodacydo/work/project to either sys.path or $PYTHONPATH.
Do you have a file called __init__.py in the foo directory? If not then python won't recognise foo as a python package.
See the section on packages in the python tutorial for more information.
A better fix than setting PYTHONPATH is to use python -m module.path
This will correctly set sys.path[0] and is a more reliable way to execute modules.
I have a quick writeup about this problem, as other answerers have mentioned the reason for this is python path/to/file.py puts path/to on the beginning of the PYTHONPATH (sys.path).
Here is a step-by-step solution:
Add a script called run.py in /home/bodacydo/work/project and edit it like this:
import programs.my_python_program
programs.my_python_program.main()
(replace main() with your equivalent method in my_python_program.)
Go to /home/bodacydo/work/project
Run run.py
Explanation:
Since python appends to PYTHONPATH the path of the script from which it runs, running run.py will append /home/bodacydo/work/project. And voilĂ , import foo.tasks will be found.
Example solution for adding the library to your PYTHONPATH.
Add the following line into your ~/.bashrc or just run it directly:
export PYTHONPATH="$PYTHONPATH:$HOME/.python"
Then link your required library into your ~/.python folder, e.g.
ln -s /home/user/work/project/foo ~/.python/
In my mind I have to consider that the foo folder is a stand-alone library. I might want to consider moving it to the Lib\site-packages folder within a python installation. I might want to consider adding a foo.pth file there.
I know it's a library since the ./programs/my_python_program.py contains the following line:
from foo.tasks import my_function
So it doesn't matter that ./programs is a sibling folder to ./foo. It's the fact that my_python_program.py is run as a script like this:
python ./programs/my_python_program.py
If you have this problem when using an instaled version, when using setup.py, make sure your module is included inside packages
setup(name='Your program',
version='0.7.0',
description='Your desccription',
packages=['foo', 'foo.bar'], # add `foo.bar` here