質問

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秒に1回。ただし、前述のpythonプログラムはサポートしません。

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

(はい、これは非常に不明瞭で、実行中のプロセスで実行する潜在的に有害なアクションです)

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

役に立ちましたか?

解決

これは非常に良い質問です。

os モジュールは os.environ posix .environ 。これはインタープリターの起動時に設定されます。つまり、標準ライブラリは getenv 関数。

これは、Unixで ctypes を使用するのがおそらく安全な場合です。超標準のlibc関数を呼び出すことになります。

他のヒント

ctypes を使用して、これを非常に簡単に行うことができます。

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

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

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

環境を外部から変更することを期待する多くのプログラムは信じられないため、起動時に渡された環境のコピーをロードすることは同等です。実装の選択につまずいただけです。

すべてのset-at-startup値とプログラム内のputenv / setenvが動作している場合、心配することはないと思います。更新された情報を実行中の実行可能ファイルに渡すには、はるかにクリーンな方法があります。

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モジュールを作成することです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top