Python:添加到 sys.path 相对于当前正在运行的脚本的最佳方法
- 2025-03-18 08:56:00
- admin 原创
- 67
问题描述:
我有一个目录,里面全是脚本(假设是project/bin
)。我还有一个库,位于project/lib
,希望脚本自动加载它。这是我通常在每个脚本顶部使用的内容:
#!/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
这有点麻烦、丑陋,而且必须粘贴在每个文件的开头。有没有更好的方法?
我真正希望的是这样的顺利的事情:
#!/usr/bin/python
import sys.path
from os.path import pardir, sep
sys.path.append_relative(pardir + sep + "lib")
import mylib
或者更好的是,当我的编辑(或具有提交权限的其他人)决定在清理过程中重新排序导入时,某些东西不会中断:
#!/usr/bin/python --relpath_append ../lib
import mylib
这不会直接移植到非 posix 平台,但它可以保持清洁。
解决方案 1:
这是我使用的:
import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))
解决方案 2:
我正在使用:
import sys,os
sys.path.append(os.getcwd())
解决方案 3:
如果你不想编辑每个文件
像安装普通 Python 库一样安装你的库
或者
设置
PYTHONPATH
为您的lib
或者如果你愿意在每个文件中添加一行,可以在顶部添加一个 import 语句,例如
import import_my_lib
保存import_my_lib.py
在 bin 中,并且import_my_lib
可以正确地将 python 路径设置为lib
你想要的任何路径
解决方案 4:
创建一个包装模块project/bin/lib
,其中包含以下内容:
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
然后你可以用以下代码替换脚本顶部的所有垃圾内容:
#!/usr/bin/python
from lib import mylib
解决方案 5:
使用 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"))
解决方案 6:
您可以从相关根目录运行该脚本python -m
。并将“模块路径”作为参数传递。
例子:$ python -m module.sub_module.main # Notice there is no '.py' at the end.
另一个例子:
$ 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
解决方案 7:
如果您不想以任何方式更改脚本内容,请将当前工作目录添加.
到 $PYTHONPATH 前面(参见下面的示例)
PYTHONPATH=.:$PYTHONPATH alembic revision --autogenerate -m "First revision"
到此结束!
解决方案 8:
我多次这样做过:
import os
import sys
current_path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(current_path, "lib"))
解决方案 9:
提供的每个答案都存在一个问题,可以总结为“只需将这个神奇的咒语添加到脚本的开头。看看只用一两行代码可以做什么。”它们不会在所有可能的情况下都起作用!
例如,一个这样的神奇咒语使用__file__
。不幸的是,如果您使用 cx_Freeze 打包脚本或使用 IDLE,这将导致异常。
另一个神奇的咒语是使用 os.getcwd()。只有当您从命令提示符运行脚本并且包含脚本的目录是当前工作目录(即您在运行脚本之前使用 cd 命令切换到该目录)时,此咒语才会起作用。天哪!我希望我不必解释为什么如果您的 Python 脚本在 PATH 中的某个位置并且您只是通过键入脚本文件的名称来运行它,那么此咒语将不起作用。
幸运的是,有一个神奇的咒语可以在我测试过的所有情况下起作用。不幸的是,这个神奇的咒语不仅仅是一两行代码。
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)
正如你所见,这绝非易事!
解决方案 10:
./bin/foo.py
我在您的示例中看到了一个 shebang。如果您以而不是 的身份运行 bin 脚本,python ./bin/foo.py
则可以选择使用 shebang 来更改$PYTHONPATH
变量。
不过,您无法直接在 shebang 中更改环境变量,因此您需要一个小的辅助脚本。将其python.sh
放入您的bin
文件夹中:
#!/usr/bin/env bash
export PYTHONPATH=$PWD/lib
exec "/usr/bin/python" "$@"
然后改变你的./bin/foo.py
一切#!bin/python.sh
解决方案 11:
我使用:
from site import addsitedir
然后,可以使用任何相对目录!
addsitedir('..lib')
;两个点表示先移动(向上)一个目录。
请记住,这完全取决于您当前的工作目录。如果是 C:\Joe\Jen\Becky,则 addsitedir('..\lib') 会导入到您的路径 C:\Joe\Jen\lib
C:\n |__Joe
|_ Jen
| |_ Becky
|_ lib
解决方案 12:
当我们尝试从终端运行带有路径的 python 文件时。
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)
保存文件(test.py)。
運行系統。
打开终端并进入保存文件的目录。然后写入
python test.py "/home/saiful/Desktop/bird.jpg"
按 Enter 键
输出:
File Name: test, Argument dir: /home/saiful/Desktop/bird.jpg
解决方案 13:
在模块之前添加以下两行:
import sys,os
sys.path.append(os.pardir)
我的文件结构如下:
.
├── common
│ ├── __init__.py
│ └── module.py
├── main.py
└── tool
├── __init__.py
└── test.py
和我的测试代码:
import sys,os
sys.path.append(os.pardir)
from common import module
def foo(a,b):
return module.sum(a,b)
if __name__ == '__main__':
print(foo(1,2))
为了能够在终端中优雅地运行工具模块中的代码,我使用:
(base) robben@Ro tool % python test.py
3
扫码咨询,免费领取项目管理大礼包!