14

環境変数への Python のアクセスは、プロセス環境に対するオペレーティング システムのビューを正確に反映していません。

os.getenv および os.environ は、特定のケースで期待どおりに機能しません。

実行中のプロセスの環境を適切に取得する方法はありますか?


私が言いたいことを示すために、2 つのほぼ同等のプログラム (最初は C で、もう 1 つは 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 秒ごとに「my value」を吐き出します。ただし、前述の python プログラムはそうではありません。

この場合、Python プログラムを C プログラムのように機能させる方法はありますか?

(はい、これは実行中のプロセスで実行する非常にあいまいで潜在的に損害を与えるアクションであることを認識しています)

また、私は現在python 2.4を使用していますが、これはpythonの新しいバージョンで修正されている可能性があります。

4

5 に答える 5

14

それはとても良い質問です。

モジュールは、インタープリターの起動時に設定されるの値にos初期化されることがわかります。つまり、標準ライブラリはgetenv関数へのアクセスを提供していないようです。os.environposix.environ

これは、 UNIX でctypesを使用することがおそらく安全なケースです。超標準の libc 関数を呼び出すためです。

于 2008-10-24T22:28:38.507 に答える
11

ctypesこれを非常に簡単に行うために使用できます。

>>> from ctypes import CDLL, c_char_p
>>> getenv = CDLL("libc.so.6").getenv
>>> getenv.restype = c_char_p
>>> getenv("HOME")
'/home/glyph'
于 2008-10-28T03:38:23.317 に答える
4

もう1つの可能性は、代わりにpdbまたは他のPythonデバッガーを使用し、CレベルではなくPythonレベルでos.environを変更することです。 これは、実行中のPythonプロセスを中断し、シグナルの受信時にPythonコンソールへのアクセスを提供するために投稿した小さなレシピです。または、中断するコードのある時点でpdb.set_trace()を貼り付けるだけです。いずれの場合も、ステートメント " import os; os.environ['SOME_VARIABLE']='my_value'"を実行するだけで、Pythonに関する限り更新する必要があります。

これによってsetenvを使用してC環境も更新されるかどうかはわかりません。したがって、getenvを直接使用するCモジュールがある場合は、これを同期させるためにさらに作業を行う必要があります。

于 2008-10-25T23:50:56.333 に答える
3

多くのプログラムが環境を外部から変更することを期待しているとは思わないので、起動時に渡された環境のコピーをロードすることは同等です。あなたは単に実装の選択に出くわしただけです。

起動時の設定値がすべて表示され、プログラム内から putenv/setenv が機能している場合は、心配する必要はないと思います。更新された情報を実行中の実行可能ファイルに渡すはるかにクリーンな方法があります。

于 2008-10-25T14:53:21.713 に答える
1

Python ソース コード (2.4.5) を見ると、次のようになります。

  • Modules/posixmodule.c は、起動時に実行される convertenviron() で環境を取得し (INITFUNC を参照)、環境をプラットフォーム固有のモジュール (nt、os2、または posix) に保存します。

  • Lib/os.py は sys.builtin_module_names を見て、posix、nt、または os2 のいずれかからすべてのシンボルをインポートします

はい、それは起動時に決定されます。ここでは os.environ は役に立ちません。

本当にこれを行いたい場合、頭に浮かぶ最も明白なアプローチは、常にシステム コールを呼び出す getenv を使用して、独自のカスタム C ベースの python モジュールを作成することです。

于 2008-10-24T22:16:52.557 に答える