通过符号链接启动Python脚本

14
我有一个可执行的Python脚本,存在于“scripts”目录中,在根目录中有一个指向该脚本的符号链接(用于启动文件)。就像这样:
.
├── scripts
│   ├── const.py
│   ├── fops.py
│   ├── i_build.py
│   └── i_Props.ini
└── build_i -> scripts/i_build.py

我希望能够通过以下方式启动/运行我的脚本:
python build_i

从根目录开始,i_build.py脚本将尝试打开i_Props.ini并根据其中的内容进行一些操作。

问题在于,当通过根目录中的符号链接启动i_build.py脚本时,i_build.py脚本将在根目录中查找其他文件(而不是存储i_build.py的/scripts目录)。

i_build.py文件的属性文件位置为:

PROP_FILE = "i_Props.ini"

尝试打开文件失败,我不想硬编码路径,这是显而易见的原因。

在主文件中添加 os.getcwd() 进行快速检测确认了我的猜想,它认为当前工作目录是根目录,并且对 __file__ 的检查显示它是符号链接 ("build_i")。

有什么办法让Python使用符号链接的目标文件作为 __file__ 名称和当前工作目录吗?


你可能可以使用kqueue或其他操作系统上的类似工具来监视文件系统。最终区分这两个位置的可能是启动执行的inode。但是,如果没有进行一些挖掘,这些都不会很清楚地暴露出来。我能想到的另一件事就是硬链接而不是软链接,但我认为这可能会完全产生相反的效果。有一些shell技巧可以做到,我相信Z shell有一个“在运行程序之前”的钩子,可以将您真正的cwd作为参数提供给脚本。 - synthesizerpatel
这不值得回答,所以我在评论中回复。您可以使用 os.readlink() 读取符号链接,并使用 subprocess.Popen()从结果运行脚本。有些笨拙,但作为没有硬编码并且不添加依赖项的解决方案来完成工作。 - ThinkChaos
如何在Python中获取当前执行文件的路径? - jfs
3个回答

20

你可以使用 __file__,但是你必须采取一些预防措施来获得真实路径:

import os
base_dir = os.path.dirname(os.path.realpath(__file__))

然后相对于 base_dir 加载你的其他文件/资源:

some_subdir = 'my_subdir'
some_file = 'my.ini'

ini_path = os.path.join(base_dir, some_subdir, some_file)

1
__file__ 可能未定义,在这种情况下可以回退到 sys.argv[0] - jfs

3

以下是几种可能的方法:

  1. 在根目录下创建一个shell文件,通过显式路径调用你的Python脚本。
  2. 将Python文件所在的目录添加到你的path环境变量中。
  3. 特别地,将该目录添加到sys.path中。

选项1可能是我的解决方法... 2和3本质上仍然是硬编码。我需要避免涉及额外步骤的任何事情,因为这将分发给许多人,被搞乱的环境变量越少越好。 - Mike
在 Linux 上,如果您将 Bash 脚本添加到 /etc、/bin 或 /usr/etc 中,则可以直接执行它而无需指定路径。 - Steve Barnes

0

从符号链接启动Python脚本并使脚本使用链接目标路径的最简单方法是:

os.chdir("<path to link destination>")

例如,我喜欢将我的脚本及其相关文件放在/usr/local/lib/myapp中。
为了方便起见,我在/usr/local/bin中创建了一个到/usr/local/lib/myapp/myapp.py的符号链接。
cd /usr/local/bin
ln -s ../lib/myapp/myapp.py myapp

在我的 myapp.py 文件中,我会有这样的代码:

os.chdir("/usr/local/lib/myapp")
# put any import statements for myapp files here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接