0

I want to run a program from my Python script.

In cmd, I would do this:

cd C:\Program Files (x86)\Tools\Converter
Converter.exe -i "C:\Temp\20220902-0001.csv" -o "C:\Temp\20220902-0001.mf4" -f --p-filetype Csv --p-rowsignalnames 1 --p-rowsignalunits 2 --p-rowdatabegin 4 --p-csvseparator Semicolon --p-mastersignalnames Time;

I tried this code to emulate that from my script:

import subprocess

convvers = subprocess.Popen(['Converter.exe', '-i "C:\\Temp\\20220902-0001.csv" -o "C:\\Temp\\20220902-0001.mf4" -f --p-filetype Csv --p-rowsignalnames 1 --p-rowsignalunits 2 --p-rowdatabegin 4 --p-csvseparator Semicolon --p-mastersignalnames Time'], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd="C:\\Program Files (x86)\\Tools\\Converter")

but I got an error:

ERROR(S):
  Required option 'o, output-file' is missing.

What is wrong? How do I fix it?

Mani
  • 9
  • 2
  • It looks like your second command the -i doesn't get closed until much later than it should. The subprocess should be a list of arguments so you want each argument to be a list item. Also ensure the converter.exe is in the same folder as the python script. Generally better to use full paths. – JerodG Sep 16 '22 at 15:07
  • Welcome to Stack Overflow. Please read [ask]. I [edit]ed the post to show how to ask a question clearly and directly, and to improve the formatting. As an aside, it is worth putting some effort into studying how the command line works, and how command-line arguments to programs work in general. There are some interesting and surprising cases where you can start programs from the command line and get special effects (for example, starting Firefox directly loading the profile manager). – Karl Knechtel Sep 16 '22 at 15:26

1 Answers1

0

Either allow the shell to split up the arguments, or do it yourself. Mixing and matching won't turn out well. Furthermore, by writing something like 'foo r"bar"', you put the actual letter r and the double-quotes into the string; keep in mind that this syntax is only meaningful in the Python code itself, not at the command line.

Using the shell (not recommended except where necessary), pass a single string with the command as you would type it in the terminal:

subprocess.Popen(
    r'Converter.exe -i C:\Temp\20220902-0001.csv -o C:\Temp\20220902-0001.mf4',
    shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    cwd=r'C:\Program Files (x86)\Tools\Converter'
)

Notice I used raw strings to avoid doubling up the backslashes. Keep in mind that the string literal will be processed twice: first by Python to determine what is actually in the string that makes up the command line, and then by the shell to split it into individual tokens (i.e., what would be sys.argv if you were calling another Python script).

This is important for portability: the Windows shell will expect \ to be part of a file path, but Linux and Mac will treat it as an escape character. On those systems, if you needed to include \ in an argument for some reason (unusual, since it isn't a path separator there), you would have to double it up even when using a raw string. On the other hand, on those systems you can use \ to escape spaces in file names instead of quoting the name.

Different shells also have their own rules for how quoting works.

Note well that, for example, the -i and the C:\Temp\20220902-0001.csv will be separate arguments. This is by design, and what the program expects.

Doing the tokenization yourself (recommended):

subprocess.Popen(
    [
        'Converter.exe', '-i', r'C:\Temp\20220902-0001.csv',
        '-o', r'C:\Temp\20220902-0001.mf4',
    ],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    cwd=r'C:\Program Files (x86)\Tools\Converter'
)

Each element of the list will be an argument; we don't do any escaping or quoting to help out the shell, because the shell doesn't examine the arguments - they are passed directly.

Please also read Windows path in Python. It is normally not necessary to use backslashes (or worry about the problems they cause) for Windows paths, even at the command line. It is extremely likely that the code will work fine using forward slashes in the path instead:

subprocess.Popen(
    [
        'Converter.exe', '-i', 'C:/Temp/20220902-0001.csv',
        '-o', 'C:/Temp/20220902-0001.mf4',
    ],
    stdin=subprocess.PIPE, stdout=subprocess.PIPE,
    cwd='C:/Program Files (x86)/Tools/Converter'
)
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153