I have a directory full of scripts (let’s say project/bin). I also have a library located in project/lib and want the scripts to automatically load it. This is what I normally use at the top of each script:
#!/usr/bin/python from os.path import dirname, realpath, sep, pardir import sys sys.path.append(dirname(realpath(__file__)) + sep + pardir + sep + "lib") # ... now the real code import mylib
This is kind of cumbersome, ugly, and has to be pasted at the beginning of every file. Is there a better way to do this?
Really what I’m hoping for is something as smooth as this:
#!/usr/bin/python import sys.path from os.path import pardir, sep sys.path.append_relative(pardir + sep + "lib") import mylib
Or even better, something that wouldn’t break when my editor (or someone else who has commit access) decides to reorder the imports as part of its clean-up process:
#!/usr/bin/python --relpath_append ../lib import mylib
That wouldn’t port directly to non-posix platforms, but it would keep things clean.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
This is what I use:
import os, sys sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))
Method 2
I’m using:
import sys,os sys.path.append(os.getcwd())
Method 3
If you don’t want to edit each file
- Install you library like a normal python libray
or - Set
PYTHONPATHto yourlib
or if you are willing to add a single line to each file, add a import statement at top e.g.
import import_my_lib
keep import_my_lib.py in bin and import_my_lib can correctly set the python path to whatever lib you want
Method 4
Create a wrapper module project/bin/lib, which contains this:
import sys, os
sys.path.insert(0, os.path.join(
os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib'))
import mylib
del sys.path[0], sys, os
Then you can replace all the cruft at the top of your scripts with:
#!/usr/bin/python from lib import mylib
Method 5
If you don’t want to change the script content in any ways, prepend the current working directory . to $PYTHONPATH (see example below)
PYTHONPATH=.:$PYTHONPATH alembic revision --autogenerate -m "First revision"
And call it a day!
Method 6
Using python 3.4+
import sys from pathlib import Path # As PosixPath sys.path.append(Path(__file__).parent / "lib") # Or as str as explained in https://stackoverflow.com/a/32701221/11043825 sys.path.append(str(Path(__file__).parent / "lib"))
Method 7
You can run the script with python -m from the relevant root dir. And pass the “modules path” as argument.
Example: $ python -m module.sub_module.main # Notice there is no '.py' at the end.
Another example:
$ tree # Given this file structure
.
├── bar
│ ├── __init__.py
│ └── mod.py
└── foo
├── __init__.py
└── main.py
$ cat foo/main.py
from bar.mod import print1
print1()
$ cat bar/mod.py
def print1():
print('In bar/mod.py')
$ python foo/main.py # This gives an error
Traceback (most recent call last):
File "foo/main.py", line 1, in <module>
from bar.mod import print1
ImportError: No module named bar.mod
$ python -m foo.main # But this succeeds
In bar/mod.py
Method 8
This is how I do it many times:
import os import sys current_path = os.path.dirname(os.path.abspath(__file__)) sys.path.append(os.path.join(current_path, "lib"))
Method 9
There is a problem with every answer provided that can be summarized as “just add this magical incantation to the beginning of your script. See what you can do with just a line or two of code.” They will not work in every possible situation!
For example, one such magical incantation uses __file__. Unfortunately, if you package your script using cx_Freeze or you are using IDLE, this will result in an exception.
Another such magical incantation uses os.getcwd(). This will only work if you are running your script from the command prompt and the directory containing your script is the current working directory (that is you used the cd command to change into the directory prior to running the script). Eh gods! I hope I do not have to explain why this will not work if your Python script is in the PATH somewhere and you ran it by simply typing the name of your script file.
Fortunately, there is a magical incantation that will work in all the cases I have tested. Unfortunately, the magical incantation is more than just a line or two of code.
import inspect
import os
import sys
# Add script directory to sys.path.
# This is complicated due to the fact that __file__ is not always defined.
def GetScriptDirectory():
if hasattr(GetScriptDirectory, "dir"):
return GetScriptDirectory.dir
module_path = ""
try:
# The easy way. Just use __file__.
# Unfortunately, __file__ is not available when cx_Freeze is used or in IDLE.
module_path = __file__
except NameError:
if len(sys.argv) > 0 and len(sys.argv[0]) > 0 and os.path.isabs(sys.argv[0]):
module_path = sys.argv[0]
else:
module_path = os.path.abspath(inspect.getfile(GetScriptDirectory))
if not os.path.exists(module_path):
# If cx_Freeze is used the value of the module_path variable at this point is in the following format.
# {PathToExeFile}{NameOfPythonSourceFile}. This makes it necessary to strip off the file name to get the correct
# path.
module_path = os.path.dirname(module_path)
GetScriptDirectory.dir = os.path.dirname(module_path)
return GetScriptDirectory.dir
sys.path.append(os.path.join(GetScriptDirectory(), "lib"))
print(GetScriptDirectory())
print(sys.path)
As you can see, this is no easy task!
Method 10
I see a shebang in your example. If you’re running your bin scripts as ./bin/foo.py, rather than python ./bin/foo.py, there’s an option of using the shebang to change $PYTHONPATH variable.
You can’t change environment variables directly in shebangs though, so you’ll need a small helper script. Put this python.sh into your bin folder:
#!/usr/bin/env bash
export PYTHONPATH=$PWD/lib
exec "/usr/bin/python" "[email protected]"
And then change the shebang of your ./bin/foo.py to be #!bin/python.sh
Method 11
When we try to run python file with path from terminal.
import sys
#For file name
file_name=sys.argv[0]
#For first argument
dir= sys.argv[1]
print("File Name: {}, argument dir: {}".format(file_name, dir)
Save the file (test.py).
Runing system.
Open terminal and go the that dir where is save file.
then write
python test.py "/home/saiful/Desktop/bird.jpg"
Hit enter
Output:
File Name: test, Argument dir: /home/saiful/Desktop/bird.jpg
Method 12
I use:
from site import addsitedir
Then, can use any relative directory !
addsitedir('..lib') ; the two dots implies move (up) one directory first.
Remember that it all depends on what your current working directory your starting from.
If C:JoeJenBecky, then
addsitedir(‘..lib’) imports to your path C:JoeJenlib
C:
|__Joe
|_ Jen
| |_ Becky
|_ lib
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0