0

I am trying to run AVL (Athena Vortex Lattice) with Python. It's a software that runs on a separate terminal window, exactly like XFOIL. The user writes commands and presses enter to execute.

I am using the subprocess module to run the software, and the terminal window opens as expected. However, I can't get my Python program to write commands into the opened window. I don't get any error, but nothing is written to AVL, and it stays in its initial state.

The command I am trying to write to AVL is LOAD followed by an absolute path to an input file.

This is the first time I'm using the subprocess module, so I may just have forgotten an essential option somewhere. I'm running the program with Python 3.9 on macOS.

What could be wrong?

import os.path
import subprocess as sp

AVL_FOLDER_PATH = '~/Desktop/AVL_VLM'
AVL_EXE_NAME = 'avl335'
avl_path = os.path.join(AVL_FOLDER_PATH, AVL_EXE_NAME)
avl_open_cmd = 'open ' + avl_path

avl_ps = sp.Popen([avl_open_cmd], stdin=sp.PIPE, stdout=None, stderr=None, shell=True)

def avl_command(cmd):
    cmd += '\n'
    cmd = cmd.encode('ascii')
    avl_ps.stdin.write(cmd)

avl_command('LOAD')
avl_command('/Users/vianneydubois/Desktop/AVL_VLM/test_gen.avl')
UCYT5040
  • 367
  • 3
  • 15
  • `shell=True` is probably wrong here, but then your command needs to be `['open', avl_path]`. Perhaps see also [Actual meaning of `shell=True` in `subprocess`](https://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess)... and probably get Python to expand the tilde in the path for you. – tripleee Jun 01 '21 at 17:48
  • From what I can tell from the AVL docs, the LOAD command and the filename should be on the same line, separated by a space. You're putting them on different lines entirely. – jasonharper Jun 01 '21 at 17:53
  • The LOAD command and filename can be on different lines, it works when I do it manually and I have already seen automated scripts using a command per line, so this is not where the problem is I think... – vianndub Jun 01 '21 at 17:55
  • Why do you need the `open` at all here? If `avl335` is actually the name of your executable, then just run that. `open` is a MacOS thing that tries to find the executable associated with a given data file. – Tim Roberts Jun 01 '21 at 18:36
  • plus you can't have spaces in your command line. Open and your path need to be part of the list. – eatmeimadanish Jun 01 '21 at 18:41
  • @TimRoberts Thank you for your advice! I was taught this way to run an executable, so I modified the code to call `./avl335` and it runs, but it seems that my command is not sent until I quit AVL by manually writing the QUIT command – vianndub Jun 01 '21 at 19:07

2 Answers2

1

input/output is buffered by default (https://docs.python.org/3/library/subprocess.html#subprocess.Popen)

you can set bufsize=0 in Popen:

0 means unbuffered (read and write are one system call and can return short)

(https://docs.python.org/3/library/subprocess.html#subprocess.Popen)

as an alternative, you could flush the buffer manually after write:

avl_ps.stdin.write(cmd)
avl_ps.stdin.flush()
Cyril Jouve
  • 990
  • 5
  • 15
  • I added a `.flush()`after my command writing, and it is almost working... The new problem is, when I add more commands, the program stops during the execution, at a random position. What I mean is that if I run the Python program multiple times, the AVL execution is stopped before it is finished, an it is always at a different time, sometimes it is stopped right at the beginning, sometimes it is during the computation, after a few commands have been successfully written – vianndub Jun 01 '21 at 19:29
0

Is this really what you are intending?

import os.path
import subprocess as sp

AVL_FOLDER_PATH = '~/Desktop/AVL_VLM'
AVL_EXE_NAME = 'avl335'
avl_path = os.path.join(AVL_FOLDER_PATH, AVL_EXE_NAME)


def avl_command(cmd):
    return sp.run(cmd, capture_output=True, shell=True)

ret = avl_command(['open ', avl_path])
ret = avl_command(['LOAD','/Users/vianneydubois/Desktop/AVL_VLM/test_gen.avl'])

or do you mean:

ret = avl_command('open' + avl_path + '; LOAD /Users/vianneydubois/Desktop/AVL_VLM/test_gen.avl')
print(ret.stdout.decode())
eatmeimadanish
  • 3,809
  • 1
  • 14
  • 20
  • I tried your code, removed the `open` command as advised above by Tim Roberts, but the result is the same, AVL runs in terminal, but the LOAD and following commands are not written in AVL – vianndub Jun 01 '21 at 19:15
  • What is the LOAD command doing, does that take inputs? Or is this all part of the initial open command? – eatmeimadanish Jun 01 '21 at 19:52
  • The LOAD command asks the user to write an input file name. You can either write `LOAD myfile.avl` or separately `LOAD` then `myfile.avl`. Then the program reads the input file. – vianndub Jun 01 '21 at 20:10
  • So my first option is what you want. You are wanting this in the same session? – eatmeimadanish Jun 01 '21 at 21:18