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

发布于 2024-12-23 01:44:02 字数 739 浏览 1 评论 0原文

我有一个充满脚本的目录(比如说 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 平台,但它会让事情保持干净。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

记忆で 2024-12-30 01:44:02

这就是我使用的:

import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))

This is what I use:

import os, sys
sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))
单挑你×的.吻 2024-12-30 01:44:02

我正在使用:

import sys,os
sys.path.append(os.getcwd())

I'm using:

import sys,os
sys.path.append(os.getcwd())
心欲静而疯不止 2024-12-30 01:44:02

如果您不想编辑每个文件,

  • 请像普通 python 库一样安装库
  • PYTHONPATH 设置为您的 lib

,或者如果您愿意向每个文件添加一行,请在顶部添加导入语句,例如

import import_my_lib

保留 import_my_lib.py bin 中的 code> 和 import_my_lib 可以正确地将 python 路径设置为你想要的任何 lib

If you don't want to edit each file

  • Install you library like a normal python libray
    or
  • Set PYTHONPATH to your lib

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

做个ˇ局外人 2024-12-30 01:44:02

创建一个包装器模块 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

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
霓裳挽歌倾城醉 2024-12-30 01:44:02

使用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"))

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"))
_畞蕅 2024-12-30 01:44:02

您可以使用 python -m 从相关根目录运行脚本。并将“模块路径”作为参数传递。

示例: $ python -m module.sub_module.main # 注意末尾没有“.py”。


另一个示例:

$ 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

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
金兰素衣 2024-12-30 01:44:02

如果您不想以任何方式更改脚本内容,请将当前工作目录 . 添加到 $PYTHONPATH (参见下面的示例)

PYTHONPATH=.:$PYTHONPATH alembic revision --autogenerate -m "First revision"

并收工!

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!

情定在深秋 2024-12-30 01:44:02

我多次都是这样做的:

import os
import sys

current_path = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(current_path, "lib"))

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"))
我不吻晚风 2024-12-30 01:44:02

提供的每个答案都存在一个问题,可以概括为“只需将这个神奇的咒语添加到脚本的开头即可。看看只用一两行代码可以做什么。” 它们不会在所有可能的情况下都起作用!

例如,一个这样的神奇咒语使用__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)

正如您所看到的,这不是一件容易的事!

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!

染柒℉ 2024-12-30 01:44:02

我在你的例子中看到了一个shebang。如果您以 ./bin/foo.py 运行 bin 脚本,而不是 python ./bin/foo.py,则可以选择使用 shebang更改 $PYTHONPATH 变量。

不过,您无法直接在 shebangs 中更改环境变量,因此您需要一个小的帮助程序脚本。将这个python.sh放入您的bin文件夹中:

#!/usr/bin/env bash
export PYTHONPATH=$PWD/lib
exec "/usr/bin/python" "$@"

然后将您的./bin/foo.py的shebang更改为#!bin/python.sh

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" "$@"

And then change the shebang of your ./bin/foo.py to be #!bin/python.sh

流星番茄 2024-12-30 01:44:02

我使用:

from site import addsitedir

然后,可以使用任何相对目录!
addsitedir('..\lib') ;两个点表示首先移动(上移)一个目录。

请记住,这完全取决于您当前的工作目录是从哪个目录开始的。
如果 C:\Joe\Jen\Becky,那么
addsitedir('..\lib') 导入到您的路径 C:\Joe\Jen\lib

C:\
  |__Joe
      |_ Jen
      |     |_ Becky
      |_ lib

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:\Joe\Jen\Becky, then
addsitedir('..\lib') imports to your path C:\Joe\Jen\lib

C:\
  |__Joe
      |_ Jen
      |     |_ Becky
      |_ lib
静谧幽蓝 2024-12-30 01:44:02

当我们尝试从终端运行带有路径的 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"

Hit Enter

输出:

File Name: test, Argument dir: /home/saiful/Desktop/bird.jpg

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
温折酒 2024-12-30 01:44:02

在模块之前添加这两行:

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

Add these two lines before your module:

import sys,os
sys.path.append(os.pardir)

My file structure as below:

.
├── common
│   ├── __init__.py
│   └── module.py
├── main.py
└── tool
    ├── __init__.py
    └── test.py

and my test code:

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))

So that I can run my code in tool module elegantly in terminal, I use:

(base) robben@Ro tool % python test.py 
3
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文