Question about envvars

Stephen J. Turner sjturner at ix.netcom.com
Mon Jun 7 13:15:36 EDT 1999


Hi Rob,

> I have built a shared module that reads flat files for environment
> variable information, and makes subsequent putenv calls for those
> pertinent ones.  This functionality is encapsulated in a c++ class,
> FileRegistry, which I think I have working correctly, using shadow
> classes under python.  All I expose in the class is the ctor, the dtor,
> and the method called exportEnvVars():
> 
> %module MDIreg
> %{
> #include "fileregistry.h"
> %}
> 
> class FileRegistry
> {
> public:
>   FileRegistry(bool, bool);
>  ~FileRegistry();
>   void exportEnvVars();
> };
> 
> ...
> 
> However, I can't seem to get the envvars to persist into the current
> process space.  If I fork off a child, then I can see the envvars that I
> expect.

The problem is that, although putenv does indeed modify the current
process's environment, Python only reads the environment when the posix
module (imported by os) is first imported, so as to create the environ
dictionary.  (Try confirming this behavior by postponing "import os"
until after your call to MDIreg.exportEnvVars.  You should see your
environment changes reflected in os.environ.)

The proper solution is, I think, to avoid the direct use of the putenv
function, and instead to use the Python C API to modify the os.environ
mapping (which calls putenv as a side effect).  Here is a crude C module
to do just such a thing:

-------------------- START modenv.c --------------------
#include <Python.h>

#include <stdio.h>
#include <string.h>

static PyObject *modenv_load(PyObject *self, PyObject *args)
{
  FILE *fp;
  PyObject *os, *environ, *v;
  char buf[256];
  char *file;
  char *value;

  if (!PyArg_ParseTuple(args, "s", &file))
    return NULL;

  os = PyImport_ImportModule("os");
  environ = PyObject_GetAttrString(os, "environ");

  if (fp = fopen(file, "r")) {
    while (fgets(buf, sizeof(buf), fp), !feof(fp)) {
      /* skip lines that do not contain equals sign */
      if (!(value = strchr(buf, '=')))
	continue;

      /* remove trailing newline */
      buf[strlen(buf)-1] = '\0';

      *value++ = '\0';
      v = PyString_FromString(value);
      PyMapping_SetItemString(environ, buf, v);
      Py_DECREF(v);
    }  
    fclose(fp);
  }

  Py_DECREF(environ);
  Py_DECREF(os);

  Py_INCREF(Py_None);
  return Py_None;
}

static struct PyMethodDef modenv_methods[] = {
  {"load", (PyCFunction)modenv_load, METH_VARARGS},
  {NULL, (PyCFunction)NULL, 0, NULL}
};

void initmodenv()
{
  if (!Py_InitModule4("modenv", modenv_methods, NULL, NULL,
		      PYTHON_API_VERSION))
    Py_FatalError("can't initialize module modenv");
}
-------------------- END modenv.c --------------------

Hope it helps.

Regards,
Stephen

--
Stephen J. Turner <sjturner at ix.netcom.com>




More information about the Python-list mailing list