【问题标题】:Environment Variables in Python on LinuxLinux 上 Python 中的环境变量
【发布时间】:2008-10-24 22:13:54
【问题描述】:

Python 对环境变量的访问不能准确反映操作系统对进程环境的看法。

os.getenv 和 os.environ 在特定情况下无法按预期运行。

有没有办法正确获取运行进程的环境?


为了说明我的意思,使用两个大致等效的程序(第一个用 C 语言,另一个用 python):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
    char *env;
    for(;;){
        env = getenv("SOME_VARIABLE");
        if(env)
            puts(env);
        sleep(5);
    }
}

import os
import time
while True:
    env = os.getenv("SOME_VARIABLE")
    if env is not None:
        print env
    time.sleep(5)

现在,如果我们运行 C 程序并使用 gdb 附加到正在运行的进程,并通过执行以下操作强制更改引擎盖下的环境:

(gdb) print setenv("SOME_VARIABLE", "my value", 1)
[Switching to Thread -1208600896 (LWP 16163)]
$1 = 0
(gdb) print (char *)getenv("SOME_VARIABLE")
$2 = 0x8293126 "my value"

然后前面提到的 C 程序将开始每 5 秒喷出一次“我的价值”。但是,前面提到的 python 程序不会。

在这种情况下,有没有办法让 python 程序像 C 程序一样运行?

(是的,我意识到这是对正在运行的进程执行的非常晦涩且可能具有破坏性的操作)

另外,我目前使用的是 python 2.4,这可能已在更高版本的 python 中修复。

【问题讨论】:

  • 对于它的价值,这并不意外:os 模块的库参考突出了这个问题。

标签: python gdb environment-variables


【解决方案1】:

这是一个很好的问题。

原来os 模块将os.environ 初始化为posix.environ 的值,这是在解释器启动时设置的。换句话说,标准库似乎不提供对getenv 函数的访问。

在这种情况下,在 unix 上使用 ctypes 可能是安全的。因为你会调用一个超标准的 libc 函数。

【讨论】:

    【解决方案2】:

    您可以使用ctypes 非常简单地做到这一点:

    >>> from ctypes import CDLL, c_char_p
    >>> getenv = CDLL("libc.so.6").getenv
    >>> getenv.restype = c_char_p
    >>> getenv("HOME")
    '/home/glyph'
    

    【讨论】:

      【解决方案3】:

      另一种可能性是使用 pdb 或其他一些 python 调试器,并在 python 级别而不是 C 级别更改 os.environ。 Here's 我发布的一个小秘诀是为了中断正在运行的 python 进程并在接收到信号时提供对 python 控制台的访问。或者,只需在要中断的代码中的某个位置粘贴一个 pdb.set_trace() 即可。在任何一种情况下,只需运行语句“import os; os.environ['SOME_VARIABLE']='my_value'”,就 python 而言,您应该得到更新。

      我不确定这是否也会用 setenv 更新 C 环境,所以如果你有 C 模块直接使用 getenv,你可能需要做更多的工作来保持同步。

      【讨论】:

        【解决方案4】:

        我不相信许多程序会期望对其环境进行外部修改,因此在启动时加载传递的环境的副本是等效的。您只是偶然发现了一个实现选择。

        如果您在程序中看到所有启动时设置的值和 putenv/setenv 工作正常,我认为没有什么需要担心的。有更简洁的方法可以将更新的信息传递给正在运行的可执行文件。

        【讨论】:

          【解决方案5】:

          看Python源码(2.4.5):

          • Modules/posixmodule.c 在 convertenviron() 中获取环境,该环境在启动时运行(请参阅 INITFUNC)并将环境存储在特定于平台的模块(nt、os2 或 posix)中

          • Lib/os.py 查看 sys.builtin_module_names,并从 posix、nt 或 os2 导入所有符号

          所以是的,它是在启动时决定的。 os.environ 在这里不会有帮助。

          如果您真的想这样做,那么想到的最明显的方法是创建您自己的基于 C 的自定义 python 模块,并使用始终调用系统调用的 getenv。

          【讨论】:

          • 或者我可以使用 ctypes 模块,但这只会破坏它现在的乐趣,不是吗?
          猜你喜欢
          • 2016-04-08
          • 2014-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-04
          • 1970-01-01
          相关资源
          最近更新 更多