【问题标题】:Is there a way in Python to check whether an entry to os.environ is a variable or a shell function?Python中有没有办法检查os.environ的条目是变量还是shell函数?
【发布时间】:2013-12-14 02:30:05
【问题描述】:

使用 Python 中的 os 模块,我们可以通过字典 os.environ 轻松访问环境变量。但是,我发现os.environ 不仅包含变量,还包含全局定义的 shell 函数(例如来自 module 软件包)。

是否有可能从 Python 中找出os.environ 中的给定条目是否实际上是一个函数而不是一个变量?请注意,首选与外壳无关的解决方案,但我也可以选择特定于 Bash 的解决方案。

【问题讨论】:

  • 是python函数,还是bash shell函数?
  • 您可以检查 Python 变量以查看它是否可以按照此处所述进行调用:stackoverflow.com/questions/624926/… 但我对您将 shell 函数添加到 os.environ 的操作很感兴趣。这对我来说似乎很奇怪。
  • 如下所示,如果您使用export -f fndeclare -fx fn 导出shell 函数,那么函数fn 将在os.environ 中结束。
  • @VooDooNOFX:我试图找出一个 bash shell 函数。
  • @Thrustmaster: export tt='() aw, dayum!; echo $tt 给我留下了() aw, dayum!,所以在这种情况下我们会得到一个误报。由于这是一个将部署在非常异构的系统上的脚本,我不能指望没有任何可变内容以 () 开头。

标签: python bash shell environment-variables


【解决方案1】:

此功能是 bash 特有的,因此对导出的 shell 函数的测试需要执行 Bash 所做的工作。实验和source code 表明,Bash 在启动时通过其值中存在() { 前缀将环境变量识别为shell 函数——如果前缀丢失,或者甚至稍有改变,该变量将被视为普通数据变量。

因此,等效的 Python 检查如下所示:

def is_env_shell_func(name):
    return os.environ[name].startswith('() {')

【讨论】:

  • 再一次,我认为这将为任何以() { 开头的变量返回True,而不仅仅是函数。
  • @MichaelSchlottke 这是一个功能,因为这正是the shell does 识别这些变量的原因。我现在修改了答案以提及这一点。
  • 对不起,我不关注...如果我创建一个变量为export not_a_function='() { wololo }' and run declare -f not_a_function, it tells by way of return code 1`,那么not_a_function 实际上不是一个函数。但也许我误解了你。
  • @MichaelSchlottke 我在 Bash 4.2.45 中得到的是 error importing function definition for not_a_function'` 在启动子 shell 时,所以 Bash 显然 尝试 定义函数。如果您通过在右大括号之前包含换行符来修复定义以使其正常工作,那么定义测试并正常工作。
  • 您愿意发布您用来触发所描述行为的代码行吗?我无法使用 Bash 3.2 或 4.1 重现它。
【解决方案2】:

我发现一个可行的解决方案(但这非常笨拙)如下:

import subprocess

var = 'my_variable_name_i_want_to_check'
p = subprocess.Popen('declare -f ' + var, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.communicate()

if p.returncode == 0:
    print('function')
else:
    print('variable')

【讨论】:

    【解决方案3】:

    你确定os.environ中有shell函数吗?

    {master>}% function test_fn() {
    function> echo "Hello";
    function> }
    {master>}% test_fn
    Hello
    {master>}% python
    Python 2.7.3 (default, Jan  2 2013, 13:56:14) 
    [GCC 4.7.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import os
    >>> os.environ['test_fn']
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python2.7/UserDict.py", line 23, in __getitem__
        raise KeyError(key)
    KeyError: 'test_fn'
    >>> os.environ.keys()
    ['SSH_ASKPASS', 'PS_FORMAT', 'GIT_PS1_SHOWDIRTYSTATE', 'GNOME_DESKTOP_SESSION_ID', 'WINDOWPATH', 'LOGNAME', 'USER', 'GNOME_KEYRING_CONTROL', 'HOME', 'PS1', 'DISPLAY', 'PATH', 'LANG', 'TERM', 'SHELL', 'SSH_AGENT_PID', 'XAUTHORITY', 'LANGUAGE', 'GIT_PS1_SHOWSTASHSTATE', 'SHLVL', 'GIT_PS1_SHOWUPSTREAM', 'WINDOWID', 'EDITOR', 'MANPATH', 'GIT_PS1_SHOWCOLORHINTS', 'GPG_AGENT_INFO', 'USERNAME', 'WORKON_HOME', 'COLORTERM', 'WORDCHARS', 'SSH_AUTH_SOCK', 'TMUX', 'GDMSESSION', 'XDG_SESSION_COOKIE', 'LS_OPTIONS', 'DBUS_SESSION_BUS_ADDRESS', '_', 'VIRTUALENVWRAPPER_HOOK_DIR', 'VIRTUALENVWRAPPER_PROJECT_FILENAME', 'DESKTOP_SESSION', 'GIT_PS1_SHOWUNTRACKEDFILES', 'GNOME_KEYRING_PID', 'WINDOW_MANAGER', 'ZBEEP', 'PYTHONSTARTUP', 'OLDPWD', 'SESSION_MANAGER', 'XDG_DATA_DIRS', 'PWD', 'CFLAGS', 'VIRTUALENVWRAPPER_LOG_DIR', 'LS_COLORS', 'TMUX_PANE']
    >>> 
    

    【讨论】:

    • 是的,在调用子进程之前,您需要:export -f test_fn
    • 是的,或者您可以使用declare -fx test_fn
    猜你喜欢
    • 1970-01-01
    • 2012-03-25
    • 2016-08-08
    • 2011-02-19
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 2011-04-01
    • 2011-05-07
    相关资源
    最近更新 更多