Variables de entorno en Python en Linux

El acceso de Python a las variables de entorno no refleja con precisión la visión del sistema operativo del entorno de procesos.

os.getenv y os.environ no funcionan como se esperaba en casos particulares.

¿Hay alguna manera de obtener adecuadamente el entorno del proceso en ejecución?


Para demostrar lo que quiero decir, tome los dos progtwigs aproximadamente equivalentes (el primero en C, el otro en python):

#include  #include  #include  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) 

Ahora, si ejecutamos el progtwig C y adjuntamos al proceso en ejecución con gdb y cambiamos el entorno debajo del capó a la fuerza haciendo algo como esto:

     (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" 

    entonces el progtwig C mencionado anteriormente comenzará a emitir “mi valor” una vez cada 5 segundos. El mencionado progtwig de python, sin embargo, no lo hará.

    ¿Hay alguna manera de hacer que el progtwig python funcione como el progtwig C en este caso?

    (Sí, me doy cuenta de que esta es una acción muy oscura y potencialmente dañina para realizar en un proceso en ejecución)

    Además, actualmente estoy usando python 2.4, esto puede haberse solucionado en una versión posterior de python.

    Related of "Variables de entorno en Python en Linux"

    Esa es una muy buena pregunta.

    Resulta que el módulo os inicializa os.environ al valor de posix .environ , que se configura en el inicio del intérprete. En otras palabras, la biblioteca estándar no parece proporcionar acceso a la función getenv .

    Ese es un caso en el que probablemente sería seguro usar ctypes en unix. Ya que estarías llamando a una función libc ultra-estándar.

    Puedes usar ctypes para hacer esto simplemente:

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

    Otra posibilidad es usar pdb, o algún otro depurador de python en su lugar, y cambiar os.environ en el nivel de python, en lugar del nivel de C. Aquí hay una pequeña receta que publiqué para interrumpir un proceso de Python en ejecución y proporcionar acceso a una consola de Python al recibir una señal. Alternativamente, simplemente pegue un pdb.set_trace () en algún punto de su código que desee interrumpir. En cualquier caso, simplemente ejecute la instrucción ” import os; os.environ['SOME_VARIABLE']='my_value' ” y debería estar actualizado en lo que respecta a python.

    No estoy seguro de si esto también actualizará el entorno C con setenv, por lo que si tiene módulos C que usan getenv directamente, es posible que tenga que trabajar un poco más para mantener esto sincronizado.

    No creo que muchos progtwigs NUNCA esperen que su entorno se modifique externamente, por lo que cargar una copia del entorno pasado al inicio es equivalente. Simplemente ha tropezado con una elección de implementación.

    Si está viendo todos los valores establecidos en el inicio y putenv / setenv dentro de su progtwig de trabajo, no creo que haya nada de qué preocuparse. Hay formas mucho más claras de pasar información actualizada a ejecutables en ejecución.

    Mirando el código fuente de Python (2.4.5):

    • Módulos / posixmodule.c obtiene el entorno en convertenviron () que se ejecuta en el inicio (ver INITFUNC) y almacena el entorno en un módulo específico de la plataforma (nt, os2 o posix)

    • Lib / os.py mira sys.builtin_module_names e importa todos los símbolos de posix, nt u os2

    Así que sí, se decide en el inicio. os.environ no va a ser de ayuda aquí.

    Si realmente desea hacer esto, entonces el enfoque más obvio que viene a la mente es crear su propio módulo de Python basado en C personalizado, con un getenv que siempre invoca la llamada al sistema.