首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >shebang:相对于脚本路径使用解释器

shebang:相对于脚本路径使用解释器
EN

Stack Overflow用户
提问于 2013-11-20 19:58:16
回答 6查看 12.2K关注 0票数 34

我试着构建在任何地方都能运行的脚本。为此,我使用了一个定制的python,它始终位于相对于脚本的父目录中。

这样,我就可以将我的软件包加载到U盘上,无论U盘安装在哪里,也不管是否安装了python,它都可以在任何地方工作。

但是,当我使用

代码语言:javascript
运行
复制
#!../python

然后,只有当脚本从其目录中被调用时,它才能工作,这当然是不可接受的。

有没有办法做到这一点,或者在目前的shebang机制下这是不可能的?

EN

回答 6

Stack Overflow用户

发布于 2015-10-20 08:04:22

this page上有一组适用于多种语言的健康的多行脚本,例如:

代码语言:javascript
运行
复制
#!/bin/sh
"exec" "`dirname $0`/python" "$0" "$@"
print copyright

如果你想要一行shebang,this answer (和问题)在细节中解释了这个问题,并建议在shebang中使用其他脚本的以下方法:

使用AWK

代码语言:javascript
运行
复制
#!/usr/bin/awk BEGIN{a=ARGV[1];sub(/[a-z_.]+$/,"python",a);system(a"\t"ARGV[1])}

使用Perl

代码语言:javascript
运行
复制
#!/usr/bin/perl -e$_=$ARGV[0];exec(s/\w+$/python/r,$_)

从11Jan21更新:

使用更新的env实用程序:

代码语言:javascript
运行
复制
$ env --version | grep env
env (GNU coreutils) 8.30
$ env --help
Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
Set each NAME to VALUE in the environment and run COMMAND.

Mandatory arguments to long options are mandatory for short options too.
  -i, --ignore-environment  start with an empty environment
  -0, --null           end each output line with NUL, not newline
  -u, --unset=NAME     remove variable from the environment
  -C, --chdir=DIR      change working directory to DIR
  -S, --split-string=S  process and split S into separate arguments;
                        used to pass multiple arguments on shebang lines

因此,现在将-S传递给env就可以了。

票数 25
EN

Stack Overflow用户

发布于 2019-08-20 13:35:55

扩展@Anton的答案,这样路径中的空格和其他特殊字符就不会失败,并解释更多关于魔术的内容。

代码语言:javascript
运行
复制
#!/bin/sh
"true" '''\'
exec "$(dirname "$(readlink -f "$0")")"/venv/bin/python "$0" "$@"
'''

__doc__ = """You will need to deliberately set your docstrings though"""

print("This script is interpretable by python and sh!")

sh和python都能理解这个巧妙的脚本。每一个都会有不同的反应。shebang之后的前2行由sh解释,并使其将exec传递给一个相对的python二进制文件(提供了相同的命令行参数)。这些相同的行被python安全地丢弃,因为它们相当于一个字符串("true"),后跟一个多行字符串(‘)。

有关这个主题的更多信息,请参阅here

票数 9
EN

Stack Overflow用户

发布于 2019-04-13 00:45:24

看过这些答案后,我决定使用特定于Python的解决方案,该解决方案实际上不会更改shebang。

此解决方案使用系统python解释器来找到所需的解释器并执行该解释器。这对我很有用,因为它允许我使用环境变量,并确保正确的解释器。

因为它使用exec,所以不会使内存使用量加倍--新的解释器取代了上一个解释器。此外,退出状态和信号将被正确处理。

它是一个python模块,由需要在此环境下运行的脚本加载。如果需要,导入此模块的副作用是启动一个新的解释器。一般来说,模块不应该有副作用,但另一种选择是在执行非系统导入之前运行模块的函数,这将违反PEP8。所以你必须选择你的毒药。

代码语言:javascript
运行
复制
"""Ensure that the desired python environment is running."""


import os
import sys


def ensure_interpreter():
    """Ensure we are running under the correct interpreter and environ."""
    abs_dir = os.path.dirname(os.path.abspath(__file__))
    project_root = os.path.normpath(os.path.join(abs_dir, '../../../'))
    desired_interpreter = os.path.join(project_root, 'bin/python')

    if os.path.abspath(sys.executable) == desired_interpreter:
        return

    env = dict(os.environ)

    def prefix_paths(key, prefix_paths):
        """Add prefix paths, relative to the project root."""
        new_paths = [os.path.join(project_root, p) for p in prefix_paths]
        new_paths.extend(env.get(key, '').split(':'))
        env[key] = ':'.join(new_paths)

    prefix_paths('PYTHONPATH', ['dir1', 'dir2'])
    prefix_paths('LD_LIBRARY_PATH', ['lib'])
    prefix_paths('PYTHON_EGG_CACHE', ['var/.python-eggs'])
    env['PROJECT_ROOT'] = project_root
    os.execvpe(desired_interpreter, [desired_interpreter] + sys.argv, env)


ensure_interpreter()

如果你不需要使用任何环境变量,你可以去掉env = dict(os.environ)os.execvpe(desired_interpreter, [desired_interpreter] + sys.argv, env)之间的所有东西。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20095351

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档