Python:添加到 sys.path 相对于当前正在运行的脚本的最佳方法

2025-03-18 08:56:00
admin
原创
68
摘要:问题描述:我有一个目录,里面全是脚本(假设是project/bin)。我还有一个库,位于project/lib,希望脚本自动加载它。这是我通常在每个脚本顶部使用的内容:#!/usr/bin/python from os.path import dirname, realpath, sep, pardir im...

问题描述:

我有一个目录,里面全是脚本(假设是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
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用