Executing Command Line Programs from Within Python

Executing command line programs from within python

The subprocess module is the preferred way of running other programs from Python -- much more flexible and nicer to use than os.system.

import subprocess
#subprocess.check_output(['ls', '-l']) # All that is technically needed...
print(subprocess.check_output(['ls', '-l']))

How do I execute a program or call a system command?

Use the subprocess module in the standard library:

import subprocess
subprocess.run(["ls", "-l"])

The advantage of subprocess.run over os.system is that it is more flexible (you can get the stdout, stderr, the "real" status code, better error handling, etc...).

Even the documentation for os.system recommends using subprocess instead:

The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function. See the Replacing Older Functions with the subprocess Module section in the subprocess documentation for some helpful recipes.

On Python 3.4 and earlier, use subprocess.call instead of .run:

subprocess.call(["ls", "-l"])

Python Script execute commands in Terminal

There are several ways to do this:

A simple way is using the os module:

import os
os.system("ls -l")

More complex things can be achieved with the subprocess module:
for example:

import subprocess
test = subprocess.Popen(["ping","-W","2","-c", "1", "192.168.1.70"], stdout=subprocess.PIPE)
output = test.communicate()[0]

How to execute a shell program taking inputs with python?

I'll try and give you some hints to get you started - though bear in mind I do not know any of your tools, i.e. waf or csp-client, but hopefully that will not matter.

I'll number my points so you can refer to the steps easily.


Point 1

If waf is a build system, I wouldn't keep running that every time you want to run your csp-client. Just use waf to rebuild when you have changed your code - that should save time.


Point 2

When you change directory to /home/augustin/workspaceGS/gs-sw-nanosoft-product-interface-application-2.5.1 and then run ./build/csp-client you are effectively running:

/home/augustin/workspaceGS/gs-sw-nanosoft-product-interface-application-2.5.1/build/csp-client -k/dev/ttyUSB1

But that is rather annoying, so I would make a symbolic link to that that from /usr/local/bin so that you can run it just with:

csp-client -k/dev/ttyUSB1

So, I would make that symlink with:

ln -s /home/augustin/workspaceGS/gs-sw-nanosoft-product-interface-application-2.5.1/build/csp-client  /usr/local/bin/csp-client

You MAY need to put sudo at the start of that command. Once you have that, you should be able to just run:

csp-client -k/dev/ttyUSB1

Point 3

Your Python code doesn't work because every os.system() starts a completely new shell, unrelated to the previous line or shell. And the shell that it starts then exits before your next os.system() command.

As a result, the cmp ident command never goes to the csp-client. You really need to send the cmp ident command on the stdin or "standard input" of csp-client. You can do that in Python, it is described here, but it's not all that easy for a beginner.

Instead of that, if you just have aa few limited commands you need to send, such as "take a picture", I would make and test complete bash scripts in the Terminal, till I got them right and then just call those from Python. So, I would make a bash script in your HOME directory called, say csp-snap and put something like this in it:

#/bin/bash

# Extend PATH so we can find "/usr/local/bin/csp-client"
PATH=$PATH:/usr/local/bin

{
# Tell client to take picture
echo "nanoncam snap"
# Exit csp-client
echo exit
} | csp-client -k/dev/ttyUSB1

Now make that executable (only necessary once) with:

chmod +x $HOME/csp-snap

And then you can test it with:

$HOME/csp-snap

If that works, you can copy the script to /usr/local/bin with:

cp $HOME/csp-snap /usr/local/bin

You may need sudo at the start again.

Then you should be able to take photos from anywhere just with:

csp-snap

Then your Python code becomes easy:

os.system('/usr/local/bin/csp-snap')

Running command lines within your Python script

You should use the subprocess module. In particular, subprocess.call will run command line programs for you.

Running a C executable from Python with command line arguments

The > that you use in your command is a shell-specific syntax for output redirection. If you want to do the same through Python, you will have to invoke the shell to do it for you, with shell=True and with a single command line (not a list).

Like this:

subprocess.run(f'/home/dev/Desktop/myfile "{inputFileName}" > "{outputFileName}"', shell=True)

If you want to do this through Python only without invoking the shell (which is what shell=True does) take a look at this other Q&A: How to redirect output with subprocess in Python?



Related Topics



Leave a reply



Submit