关于bash:在Python中有没有办法检查os.environ的条目是变量还是shell函数?

Is there a way in Python to check whether an entry to os.environ is a variable or a shell function?

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

是否可以从python内部查明os.environ中给定的条目实际上是函数而不是变量?请注意,壳不可知论的解决方案是首选的,但我也可以解决一个bash特定的解决方案。


这个特性是bash特有的,所以导出的shell函数的测试需要做bash所做的。实验和源代码表明,bash在启动时通过在其值中存在一个() {前缀将环境变量识别为shell函数-如果前缀丢失,甚至稍微改变,则将该变量视为普通数据变量。

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

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


我发现一个可行的解决方案(但这是可笑的笨拙)是:

1
2
3
4
5
6
7
8
9
10
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')


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{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']
>>>