hexagon logo

Problem with python code in macro called from Adams/Car 2018

Hello,
 
I am trying to run python code from the macro in the Adams/Car 2018.
 
The python code is following:
 
!--- Run PYTHON code
variable set variable_name=$_self.intTmp integer_value=(eval(run_python_code("import glob, os, os.path")))
variable set variable_name=$_self.intTmp integer_value=(eval(run_python_code("cwd = os.getcwd()")))
variable set variable_name=$_self.intTmp integer_value=(eval(run_python_code("filelist = glob.glob(os.path.join(cwd, 'tmp_*'))")))
variable set variable_name=$_self.intTmp integer_value=(eval(run_python_code("for f in filelist:")))
variable set variable_name=$_self.intTmp integer_value=(eval(run_python_code("   os.remove(f)")))
!
 
When the python code is called in Adams/Car 2018 then I get following error message in the log file:
 
!
! ---------------------------------------------------
!  File "<string>", line 1
!    for f in filelist:
!                     ^
! SyntaxError: unexpected EOF while parsing
!  File "<string>", line 1
!    os.remove(f)
!    ^
! IndentationError: unexpected indent
 
When I run the same python code from DOS shell with command: adams2018 python ***.py then the code runs without any problem.
 
What could be the problem?
 
Can a python for loop be started in macro with (eval(run_python_code(…)))?
 
Thanks and best regards,
Ondrej
  • Hi Ondrej!
     
    I think that you have hit a limitation of the RUN_PYTHON_CODE() function: it only accepts single-line commands.
     
    Two possible ways to go:
     
    1. Usually you'd try to get your .py commands into a .py file. Then you just exec() the Python file (or use the cmd language "file python read file_name = ...." ). This can be a bit of a pain, though, if you're not sure where your .py file is. You might need to add to sys.path, or similar, to get the PATH setup to find your .py file.
    2. Here's another Pythonic way, using a list comprehension:
     
    Python code, test this out:
     
    junk=[print(item) for item in range(4)]
     
    I've not tried with your exact code, but I think it is this:
     
    var set var=pydummy int=(eval(run_python_code("junk = [os.remove(f) for f in filelist]")))
     
     
    HTH,
    Kent
     
     
  • Hi Kent,
    thanks a lot for your answer it helped a lot.
    Both your ways are working:
    1) read python file method
    file python read &
      file_name = (eval(getenv("TOPDIR")//"/python_code/rm_files.py))
     
    2) run_python_code method
    !--- Run PYTHON code
    variable set variable_name=$_self.imp    integer_value=(eval(run_python_code("import glob, os, os.path")))
    variable set variable_name=$_self.dir    integer_value=(eval(run_python_code("dir = os.getcwd()")))
    variable set variable_name=$_self.files  integer_value=(eval(run_python_code("filelist = glob.glob(os.path.join(dir, 'tmp_*'))")))
    variable set variable_name=$_self.frmv   integer_value=(eval(run_python_code("junk = [os.remove(f) for f in filelist]")))
     Thanks for your help. 
    It is quite unfortunate that there is a limitation for single line python commads.
     
    Is MSC working on an update to run more sophisticated multiline python codes?
     
    Best regards,
    Ondrej
  • Why should someone take the burden and write Python code in command language instead of putting it in a file and edit this with an editor with syntax highlighting or even a more complex environment like IDLE, Anaconda,Spyder, PYCharm, Eclipse or whatever ?
    Especially since there is the command:
    file python read file = "xxx.py"
     
    Nevertheless:
    Have you tried to enter that code when switching the command window to Py-input ?
     
     
  • Hello Martin,
     
    it was just 5 lines of code and I wanted to avoid the python file.
     
    Best regards,
    Ondrej
  • Another workaround with four additional lines would be to dump the desired content into an intermediate python file and simply read/cleanup after creation.
     
    file text open file="test.py" open_mode = overwrite
    file text write format="import glob, os, os.path"
    file text write format="cwd = os.getcwd()"
    file text write format="filelist = glob.glob(os.path.join(cwd, 'tmp_*'))"
    file text write format="for f in filelist:"
    file text write format="  os.remove(f)"
    file text close file="test.py"
    file python read file = "test.py"
    var set var = DeleteIt int = (eval(REMOVE_FILE("test.py"))
     
    It's still using a python file, but saves the administrative work of having files installed & found on the target machine (especially TOPDIR is one of the top-forbidden zones in our IT)
  • Hello Martin,
     
    thanks a lot for another hint.
     
    Best regards,
    Ondrej
     ​
  • I have to correct myself concerning the good opinion about file python read.
    My new setting is "it sucks".
     
    Check here for details:
     
    In a nutshell: DO NOT USE use file python read. Use run_python_code("exec(open('xxx..py').read())") instead !