draksi
draksi

Reputation: 83

Command gives different behaviour in terminal or in program (Python and C++)

I am trying to execute the following command programatically:

~$ obabel -:"ccco" -O /home/user/output.png

obabel is a chemistry library, and basically if the string in the "" is complete nonsense chemically, it won't be able to generate the PNG file, and if it is a legitimate chemical structure the PNG file will be generated. This works in the terminal.

However, if I call the same command with Python, PNG files are generated for complete nonsense input strings which don't generate a PNG when the command is executed in the terminal.

I'm using subprocess like this:

cmd = 'obabel -:"ccco" -O /home/user/output.png'
proc = sub.Popen([cmd], shell=True, stderr=sub.PIPE)
res = proc.communicate()

I have also tried this:

os.system(cmd)

And tried Python2 and Python3. This happens when running scripts from the terminal or iPython.

I have also tried using C++ and running the cmd like this:

std::string cmd = "obabel -:\"ccco\" -O /home/user/output.png";
system(cmd.c_str());

Upvotes: 1

Views: 66

Answers (1)

Norrius
Norrius

Reputation: 7930

By default Popen expects a list of string arguments, but if you pass shell=True, you can supply the command as a simple string (it will be executed in a shell). Currently you are passing in a list with one string that contains the entirety of the command, instead you can use either of these:

proc = subprocess.Popen('obabel -:"ccco" -O output.png', shell=True, stderr=subprocess.PIPE)
proc = subprocess.Popen(['obabel', '-:ccco', '-O', 'output.png'], stderr=subprocess.PIPE)

Escaping the SMILES string with quotes seems to be done to protect it from the shell, and you don't need it when passing the input directly (otherwise the " characters will be a part of the string and cause invalid syntax).

Upvotes: 2

Related Questions