diff --git a/src/PYTHON/python.cpp b/src/PYTHON/python.cpp
index 11bb848b3..74591c1c1 100644
--- a/src/PYTHON/python.cpp
+++ b/src/PYTHON/python.cpp
@@ -1,427 +1,473 @@
 /* ----------------------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #include <Python.h>
 #include "python.h"
 #include "force.h"
 #include "input.h"
 #include "variable.h"
 #include "memory.h"
 #include "error.h"
 
 using namespace LAMMPS_NS;
 
 enum{NONE,INT,DOUBLE,STRING,PTR};
 
 #define VALUELENGTH 64               // also in variable.cpp
 
 /* ---------------------------------------------------------------------- */
 
 Python::Python(LAMMPS *lmp) : Pointers(lmp)
 {
   python_exists = 1;
 
   pyMain = NULL;
 
   // pfuncs stores interface info for each Python function
 
   nfunc = 0;
   pfuncs = NULL;
+
+  external_interpreter = false;
 }
 
 /* ---------------------------------------------------------------------- */
 
 Python::~Python()
 {
   // clean up
+  PyGILState_STATE gstate = PyGILState_Ensure();
 
   for (int i = 0; i < nfunc; i++) {
     delete [] pfuncs[i].name;
     deallocate(i);
     PyObject *pFunc = (PyObject *) pfuncs[i].pFunc;
     Py_XDECREF(pFunc);
   }
 
   // shutdown Python interpreter
 
-  if (pyMain) Py_Finalize();
+  if (pyMain && !external_interpreter) {
+    Py_Finalize();
+  }
+  else {
+    PyGILState_Release(gstate);
+  }
 
   memory->sfree(pfuncs);
 }
 
 /* ---------------------------------------------------------------------- */
 
 void Python::command(int narg, char **arg)
 {
   if (narg < 2) error->all(FLERR,"Invalid python command");
 
   // if invoke is only keyword, invoke the previously defined function
 
   if (narg == 2 && strcmp(arg[1],"invoke") == 0) {
     int ifunc = find(arg[0]);
     if (ifunc < 0) error->all(FLERR,"Python invoke of undefined function");
 
     char *str = NULL;
     if (noutput) {
       str = input->variable->pythonstyle(pfuncs[ifunc].ovarname,
                                          pfuncs[ifunc].name);
       if (!str)
         error->all(FLERR,"Python variable does not match Python function");
     }
 
     invoke_function(ifunc,str);
     return;
   }
 
   // parse optional args, invoke is not allowed in this mode
 
   ninput = noutput = 0;
   istr = NULL;
   ostr = NULL;
   format = NULL;
   length_longstr = 0;
   char *pyfile = NULL;
   char *herestr = NULL;
   int existflag = 0;
 
   int iarg = 1;
   while (iarg < narg) {
     if (strcmp(arg[iarg],"input") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Invalid python command");
       ninput = force->inumeric(FLERR,arg[iarg+1]);
       if (ninput < 0) error->all(FLERR,"Invalid python command");
       iarg += 2;
       istr = new char*[ninput];
       if (iarg+ninput > narg) error->all(FLERR,"Invalid python command");
       for (int i = 0; i < ninput; i++) istr[i] = arg[iarg+i];
       iarg += ninput;
     } else if (strcmp(arg[iarg],"return") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Invalid python command");
       noutput = 1;
       ostr = arg[iarg+1];
       iarg += 2;
     } else if (strcmp(arg[iarg],"format") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Invalid python command");
       int n = strlen(arg[iarg+1]) + 1;
       format = new char[n];
       strcpy(format,arg[iarg+1]);
       iarg += 2;
     } else if (strcmp(arg[iarg],"length") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Invalid python command");
       length_longstr = force->inumeric(FLERR,arg[iarg+1]);
       if (length_longstr <= 0) error->all(FLERR,"Invalid python command");
       iarg += 2;
     } else if (strcmp(arg[iarg],"file") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Invalid python command");
       delete[] pyfile;
       int n = strlen(arg[iarg+1]) + 1;
       pyfile = new char[n];
       strcpy(pyfile,arg[iarg+1]);
       iarg += 2;
     } else if (strcmp(arg[iarg],"here") == 0) {
       if (iarg+2 > narg) error->all(FLERR,"Invalid python command");
       herestr = arg[iarg+1];
       iarg += 2;
     } else if (strcmp(arg[iarg],"exists") == 0) {
       existflag = 1;
       iarg++;
     } else error->all(FLERR,"Invalid python command");
   }
 
   if (pyfile && herestr) error->all(FLERR,"Invalid python command");
   if (pyfile && existflag) error->all(FLERR,"Invalid python command");
   if (herestr && existflag) error->all(FLERR,"Invalid python command");
 
   // create or overwrite entry in pfuncs vector with name = arg[0]
 
   int ifunc = create_entry(arg[0]);
 
   // one-time initialization of Python interpreter
-  // Py_SetArgv() enables finding of *.py module files in current dir
-  //   only needed for module load, not for direct file read into __main__
   // pymain stores pointer to main module
+  PyGILState_STATE gstate;
 
   if (pyMain == NULL) {
-    if (Py_IsInitialized())
-      error->all(FLERR,"Cannot embed Python when also "
-                 "extending Python with LAMMPS");
+    external_interpreter = Py_IsInitialized();
     Py_Initialize();
-
-    //char *arg = (char *) "./lmp";
-    //PySys_SetArgv(1,&arg);
-
-    //PyObject *pName = PyString_FromString("__main__");
-    //if (!pName) errorX->all(FLERR,"Bad pName");
-    //PyObject *pModule = PyImport_Import(pName);
-    //Py_DECREF(pName);
+    PyEval_InitThreads();
+    gstate = PyGILState_Ensure();
 
     PyObject *pModule = PyImport_AddModule("__main__");
     if (!pModule) error->all(FLERR,"Could not initialize embedded Python");
     pyMain = (void *) pModule;
+  } else {
+    gstate = PyGILState_Ensure();
   }
 
   // send Python code to Python interpreter
   // file: read the file via PyRun_SimpleFile()
   // here: process the here string directly
   // exist: do nothing, assume code has already been run
 
   if (pyfile) {
     FILE *fp = fopen(pyfile,"r");
-    if (fp == NULL) error->all(FLERR,"Could not open Python file");
+
+    if (fp == NULL) {
+      PyGILState_Release(gstate);
+      error->all(FLERR,"Could not open Python file");
+    }
+
     int err = PyRun_SimpleFile(fp,pyfile);
-    if (err) error->all(FLERR,"Could not process Python file");
+
+    if (err) {
+      PyGILState_Release(gstate);
+      error->all(FLERR,"Could not process Python file");
+    }
+
     fclose(fp);
   } else if (herestr) {
     int err = PyRun_SimpleString(herestr);
-    if (err) error->all(FLERR,"Could not process Python string");
+
+    if (err) {
+      PyGILState_Release(gstate);
+      error->all(FLERR,"Could not process Python string");
+    }
   }
 
   // pFunc = function object for requested function
 
   PyObject *pModule = (PyObject *) pyMain;
   PyObject *pFunc = PyObject_GetAttrString(pModule,pfuncs[ifunc].name);
-  if (!pFunc) error->all(FLERR,"Could not find Python function");
-  if (!PyCallable_Check(pFunc))
+
+  if (!pFunc) {
+    PyGILState_Release(gstate);
+    error->all(FLERR,"Could not find Python function");
+  }
+
+  if (!PyCallable_Check(pFunc)) {
+    PyGILState_Release(gstate);
     error->all(FLERR,"Python function is not callable");
+  }
+
   pfuncs[ifunc].pFunc = (void *) pFunc;
 
   // clean-up input storage
 
   delete [] istr;
   delete [] format;
   delete [] pyfile;
+  PyGILState_Release(gstate);
 }
 
 /* ------------------------------------------------------------------ */
 
 void Python::invoke_function(int ifunc, char *result)
 {
+  PyGILState_STATE gstate = PyGILState_Ensure();
   PyObject *pValue;
   char *str;
 
   PyObject *pFunc = (PyObject *) pfuncs[ifunc].pFunc;
 
   // create Python tuple of input arguments
 
   int ninput = pfuncs[ifunc].ninput;
   PyObject *pArgs = PyTuple_New(ninput);
-  if (!pArgs) error->all(FLERR,"Could not create Python function arguments");
+
+  if (!pArgs) {
+    PyGILState_Release(gstate);
+    error->all(FLERR,"Could not create Python function arguments");
+  }
 
   for (int i = 0; i < ninput; i++) {
     int itype = pfuncs[ifunc].itype[i];
     if (itype == INT) {
       if (pfuncs[ifunc].ivarflag[i]) {
         str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
-        if (!str)
+
+        if (!str) {
+          PyGILState_Release(gstate);
           error->all(FLERR,"Could not evaluate Python function input variable");
+        }
+
         pValue = PyInt_FromLong(atoi(str));
       } else pValue = PyInt_FromLong(pfuncs[ifunc].ivalue[i]);
     } else if (itype == DOUBLE) {
       if (pfuncs[ifunc].ivarflag[i]) {
         str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
-        if (!str)
+
+        if (!str) {
+          PyGILState_Release(gstate);
           error->all(FLERR,"Could not evaluate Python function input variable");
+        }
+
         pValue = PyFloat_FromDouble(atof(str));
       } else pValue = PyFloat_FromDouble(pfuncs[ifunc].dvalue[i]);
     } else if (itype == STRING) {
       if (pfuncs[ifunc].ivarflag[i]) {
         str = input->variable->retrieve(pfuncs[ifunc].svalue[i]);
-        if (!str)
+        if (!str) {
+          PyGILState_Release(gstate);
           error->all(FLERR,"Could not evaluate Python function input variable");
+        }
         pValue = PyString_FromString(str);
       } else pValue = PyString_FromString(pfuncs[ifunc].svalue[i]);
     } else if (itype == PTR) {
       pValue = PyCObject_FromVoidPtr((void *) lmp,NULL);
     }
     PyTuple_SetItem(pArgs,i,pValue);
   }
 
   // call the Python function
   // error check with one() since only some procs may fail
 
   pValue = PyObject_CallObject(pFunc,pArgs);
-  if (!pValue) error->one(FLERR,"Python function evaluation failed");
+
+  if (!pValue) {
+    PyGILState_Release(gstate);
+    error->one(FLERR,"Python function evaluation failed");
+  }
+
   Py_DECREF(pArgs);
 
   // function returned a value
   // assign it to result string stored by python-style variable
   // or if user specified a length, assign it to longstr
 
   if (pfuncs[ifunc].noutput) {
     int otype = pfuncs[ifunc].otype;
     if (otype == INT) {
       sprintf(result,"%ld",PyInt_AsLong(pValue));
     } else if (otype == DOUBLE) {
       sprintf(result,"%.15g",PyFloat_AsDouble(pValue));
     } else if (otype == STRING) {
       char *pystr = PyString_AsString(pValue);
       if (pfuncs[ifunc].longstr) 
         strncpy(pfuncs[ifunc].longstr,pystr,pfuncs[ifunc].length_longstr);
       else strncpy(result,pystr,VALUELENGTH-1);
     }
     Py_DECREF(pValue);
   }
+
+  PyGILState_Release(gstate);
 }
 
 /* ------------------------------------------------------------------ */
 
 int Python::find(char *name)
 {
   for (int i = 0; i < nfunc; i++)
     if (strcmp(name,pfuncs[i].name) == 0) return i;
   return -1;
 }
 
 /* ------------------------------------------------------------------ */
 
 int Python::variable_match(char *name, char *varname, int numeric)
 {
   int ifunc = find(name);
   if (ifunc < 0) return -1;
   if (pfuncs[ifunc].noutput == 0) return -1;
   if (strcmp(pfuncs[ifunc].ovarname,varname) != 0) return -1;
   if (numeric && pfuncs[ifunc].otype == STRING) return -1;
   return ifunc;
 }
 
 /* ------------------------------------------------------------------ */
 
 char *Python::long_string(int ifunc)
 {
   return pfuncs[ifunc].longstr;
 }
 
 /* ------------------------------------------------------------------ */
 
 int Python::create_entry(char *name)
 {
   // ifunc = index to entry by name in pfuncs vector, can be old or new
   // free old vectors if overwriting old pfunc
 
   int ifunc = find(name);
 
   if (ifunc < 0) {
     ifunc = nfunc;
     nfunc++;
     pfuncs = (PyFunc *)
       memory->srealloc(pfuncs,nfunc*sizeof(struct PyFunc),"python:pfuncs");
     int n = strlen(name) + 1;
     pfuncs[ifunc].name = new char[n];
     strcpy(pfuncs[ifunc].name,name);
   } else deallocate(ifunc);
 
   pfuncs[ifunc].ninput = ninput;
   pfuncs[ifunc].noutput = noutput;
 
   if (!format && ninput+noutput)
     error->all(FLERR,"Invalid python command");
   else if (format && strlen(format) != ninput+noutput)
     error->all(FLERR,"Invalid python command");
 
   // process inputs as values or variables
 
   pfuncs[ifunc].itype = new int[ninput];
   pfuncs[ifunc].ivarflag = new int[ninput];
   pfuncs[ifunc].ivalue = new int[ninput];
   pfuncs[ifunc].dvalue = new double[ninput];
   pfuncs[ifunc].svalue = new char*[ninput];
 
   for (int i = 0; i < ninput; i++) {
     pfuncs[ifunc].svalue[i] = NULL;
     char type = format[i];
     if (type == 'i') {
       pfuncs[ifunc].itype[i] = INT;
       if (strstr(istr[i],"v_") == istr[i]) {
         pfuncs[ifunc].ivarflag[i] = 1;
         int n = strlen(&istr[i][2]) + 1;
         pfuncs[ifunc].svalue[i] = new char[n];
         strcpy(pfuncs[ifunc].svalue[i],&istr[i][2]);
       } else {
         pfuncs[ifunc].ivarflag[i] = 0;
         pfuncs[ifunc].ivalue[i] = force->inumeric(FLERR,istr[i]);
       }
     } else if (type == 'f') {
       pfuncs[ifunc].itype[i] = DOUBLE;
       if (strstr(istr[i],"v_") == istr[i]) {
         pfuncs[ifunc].ivarflag[i] = 1;
         int n = strlen(&istr[i][2]) + 1;
         pfuncs[ifunc].svalue[i] = new char[n];
         strcpy(pfuncs[ifunc].svalue[i],&istr[i][2]);
       } else {
         pfuncs[ifunc].ivarflag[i] = 0;
         pfuncs[ifunc].dvalue[i] = force->numeric(FLERR,istr[i]);
       }
     } else if (type == 's') {
       pfuncs[ifunc].itype[i] = STRING;
       if (strstr(istr[i],"v_") == istr[i]) {
         pfuncs[ifunc].ivarflag[i] = 1;
         int n = strlen(&istr[i][2]) + 1;
         pfuncs[ifunc].svalue[i] = new char[n];
         strcpy(pfuncs[ifunc].svalue[i],&istr[i][2]);
       } else {
         pfuncs[ifunc].ivarflag[i] = 0;
         int n = strlen(istr[i]) + 1;
         pfuncs[ifunc].svalue[i] = new char[n];
         strcpy(pfuncs[ifunc].svalue[i],istr[i]);
       }
     } else if (type == 'p') {
       pfuncs[ifunc].ivarflag[i] = 0;
       pfuncs[ifunc].itype[i] = PTR;
       if (strcmp(istr[i],"SELF") != 0)
         error->all(FLERR,"Invalid python command");
 
     } else error->all(FLERR,"Invalid python command");
   }
 
   // process output as value or variable
 
   pfuncs[ifunc].ovarname = NULL;
   pfuncs[ifunc].longstr = NULL;
   if (!noutput) return ifunc;
 
   char type = format[ninput];
   if (type == 'i') pfuncs[ifunc].otype = INT;
   else if (type == 'f') pfuncs[ifunc].otype = DOUBLE;
   else if (type == 's') pfuncs[ifunc].otype = STRING;
   else error->all(FLERR,"Invalid python command");
 
   if (length_longstr) {
     if (pfuncs[ifunc].otype != STRING) 
       error->all(FLERR,"Python command length keyword "
                  "cannot be used unless output is a string");
     pfuncs[ifunc].length_longstr = length_longstr;
     pfuncs[ifunc].longstr = new char[length_longstr+1];
   }
 
   if (strstr(ostr,"v_") != ostr) error->all(FLERR,"Invalid python command");
   int n = strlen(&ostr[2]) + 1;
   pfuncs[ifunc].ovarname = new char[n];
   strcpy(pfuncs[ifunc].ovarname,&ostr[2]);
 
   return ifunc;
 }
 
 /* ------------------------------------------------------------------ */
 
 void Python::deallocate(int i)
 {
   delete [] pfuncs[i].itype;
   delete [] pfuncs[i].ivarflag;
   delete [] pfuncs[i].ivalue;
   delete [] pfuncs[i].dvalue;
   for (int j = 0; j < pfuncs[i].ninput; j++)
     delete [] pfuncs[i].svalue[j];
   delete [] pfuncs[i].svalue;
   delete [] pfuncs[i].ovarname;
   delete [] pfuncs[i].longstr;
 }
diff --git a/src/PYTHON/python.h b/src/PYTHON/python.h
index 5f65e3970..78889b994 100644
--- a/src/PYTHON/python.h
+++ b/src/PYTHON/python.h
@@ -1,130 +1,131 @@
 /* -*- c++ -*- ----------------------------------------------------------
    LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
    http://lammps.sandia.gov, Sandia National Laboratories
    Steve Plimpton, sjplimp@sandia.gov
 
    Copyright (2003) Sandia Corporation.  Under the terms of Contract
    DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
    certain rights in this software.  This software is distributed under
    the GNU General Public License.
 
    See the README file in the top-level LAMMPS directory.
 ------------------------------------------------------------------------- */
 
 #ifndef LMP_PYTHON_H
 #define LMP_PYTHON_H
 
 #include "pointers.h"
 
 namespace LAMMPS_NS {
 
 class Python : protected Pointers {
  public:
   int python_exists;
+  bool external_interpreter;
 
   Python(class LAMMPS *);
   ~Python();
   void command(int, char **);
   void invoke_function(int, char *);
   int find(char *);
   int variable_match(char *, char *, int);
   char *long_string(int);
 
  private:
   int ninput,noutput,length_longstr;
   char **istr;
   char *ostr,*format;
   void *pyMain;
 
   struct PyFunc {
     char *name;
     int ninput,noutput;
     int *itype,*ivarflag;
     int *ivalue;
     double *dvalue;
     char **svalue;
     int otype;
     char *ovarname;
     char *longstr;
     int length_longstr;
     void *pFunc;
   };
 
   PyFunc *pfuncs;
   int nfunc;
 
   int create_entry(char *);
   void deallocate(int);
 };
 
 }
 
 #endif
 
 /* ERROR/WARNING messages:
 
 E: Invalid python command
 
 Self-explanatory.  Check the input script syntax and compare to the
 documentation for the command.  You can use -echo screen as a
 command-line option when running LAMMPS to see the offending line.
 
 E: Python invoke of undefined function
 
 Cannot invoke a function that has not been previously defined.
 
 E: Python variable does not match Python function
 
 This matching is defined by the python-style variable and the python
 command.
 
 E: Cannot embed Python when also extending Python with LAMMPS
 
 When running LAMMPS via Python through the LAMMPS library interface
 you cannot also user the input script python command.
 
 E: Could not initialize embedded Python
 
 The main module in Python was not accessible.
 
 E: Could not open Python file
 
 The specified file of Python code cannot be opened.  Check that the
 path and name are correct.
 
 E: Could not process Python file
 
 The Python code in the specified file was not run successfully by
 Python, probably due to errors in the Python code.
 
 E: Could not process Python string
 
 The Python code in the here string was not run successfully by Python,
 probably due to errors in the Python code.
 
 E: Could not find Python function
 
 The provided Python code was run successfully, but it not
 define a callable function with the required name.
 
 E: Python function is not callable
 
 The provided Python code was run successfully, but it not
 define a callable function with the required name.
 
 E: Could not create Python function arguments
 
 This is an internal Python error, possibly because the number
 of inputs to the function is too large.
 
 E: Could not evaluate Python function input variable
 
 Self-explanatory.
 
 E: Python function evaluation failed
 
 The Python function did not run successfully and/or did not return a
 value (if it is supposed to return a value).  This is probably due to
 some error condition in the function.
 
 */