From 27a6371f9b52ecc296a3dad467455a9796204b9d Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Thu, 11 May 2017 19:18:09 -0400 Subject: [PATCH] implement a `python source` command as suggested in issue #454 --- doc/src/python.txt | 22 ++++++++++++++++++---- src/PYTHON/python_impl.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/doc/src/python.txt b/doc/src/python.txt index e8a76c0e3e..748d01c2ae 100644 --- a/doc/src/python.txt +++ b/doc/src/python.txt @@ -14,7 +14,7 @@ python func keyword args ... :pre func = name of Python function :ulb,l one or more keyword/args pairs must be appended :l -keyword = {invoke} or {input} or {return} or {format} or {length} or {file} or {here} or {exists} +keyword = {invoke} or {input} or {return} or {format} or {length} or {file} or {here} or {exists} or {source} {invoke} arg = none = invoke the previously defined Python function {input} args = N i1 i2 ... iN N = # of inputs to function @@ -36,7 +36,12 @@ keyword = {invoke} or {input} or {return} or {format} or {length} or {file} or { {here} arg = inline inline = one or more lines of Python code which defines func must be a single argument, typically enclosed between triple quotes - {exists} arg = none = Python code has been loaded by previous python command :pre + {exists} arg = none = Python code has been loaded by previous python command + {source} arg = {filename} or {inline} + filename = file of Python code which will be executed immediately + inline = one or more lines of Python code which will be executed immediately + must be a single argument, typically enclosed between triple quotes +:pre :ule [Examples:] @@ -67,7 +72,8 @@ def loop(lmpptr,N,cut0): [Description:] -Define a Python function or execute a previously defined function. +Define a Python function or execute a previously defined function or +execute some arbitrary python code. Arguments, including LAMMPS variables, can be passed to the function from the LAMMPS input script and a value returned by the Python function to a LAMMPS variable. The Python code for the function can @@ -102,7 +108,8 @@ command. The {func} setting specifies the name of the Python function. The code for the function is defined using the {file} or {here} keywords -as explained below. +as explained below. In case of the {source} keyword, the name of +the function is ignored. If the {invoke} keyword is used, no other keywords can be used, and a previous python command must have defined the Python function @@ -111,6 +118,13 @@ previously defined arguments and return value processed as explained below. You can invoke the function as many times as you wish in your input script. +If the {source} keyword is used, no other keywords can be used. +The argument can be a filename or a string with python commands, +either on a single line enclosed in quotes, or as multiple lines +enclosed in triple quotes. These python commands will be passed +to the python interpreter and executed immediately without registering +a python function for future execution. + The {input} keyword defines how many arguments {N} the Python function expects. If it takes no arguments, then the {input} keyword should not be used. Each argument can be specified directly as a value, diff --git a/src/PYTHON/python_impl.cpp b/src/PYTHON/python_impl.cpp index 8c59ef1915..c492c6ab39 100644 --- a/src/PYTHON/python_impl.cpp +++ b/src/PYTHON/python_impl.cpp @@ -119,6 +119,32 @@ void PythonImpl::command(int narg, char **arg) return; } + // if source is only keyword, execute the python code + + if (narg == 3 && strcmp(arg[1],"source") == 0) { + + PyGILState_STATE gstate = PyGILState_Ensure(); + + // if argument string is file, open it + // otherwise process string as python code + + int err = 0; + FILE *fp = fopen(arg[2],"r"); + + if (fp == NULL) + err = PyRun_SimpleString(arg[2]); + else + err = PyRun_SimpleFile(fp,arg[2]); + + if (err) { + PyGILState_Release(gstate); + error->all(FLERR,"Could not process Python source command"); + } + if (fp) fclose(fp); + PyGILState_Release(gstate); + return; + } + // parse optional args, invoke is not allowed in this mode ninput = noutput = 0;