Reputation: 183
I am trying to make a repeated call on the windows command line from my python code. For each fine in a directory, I need to run a command, and wait for it to finish.
try:
directoryListing = os.listdir(inputDirectory)
for infile in directoryListing:
meshlabString = #string to pass to command line
os.system(meshlabString)
except WindowsError as winErr:
print("Directory error: " + str((winErr)))
I have been reading online, and it seems the preferred way to do this is with subprocess.call(), but I cannot figure out how to run cmd.exe through subprocess.call(). It kind of works right now using os.system(), but it gets caught up trying to run a bunch of processes at once, and dies. If someone could provide me a few lines of code on how to run a command on the windows command line, and if subprocess.wait() is the best way to wait.
Upvotes: 1
Views: 490
Reputation: 8767
You have two options, subprocess.Popen
and subprocess.call
. The main difference is that by default Popen
is non-blocking, whereas call
is blocking. This means that you can interact with Popen
while its running, but you cannot with call
. You must wait for the process to complete with call
, which you can modify Popen
to run in the same manner by utilizing wait()
.
call
itself is just a wrapper around Popen
as shown in the source:
def call(*popenargs, timeout=None, **kwargs):
"""Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute.
The arguments are the same as for the Popen constructor. Example:
retcode = call(["ls", "-l"])
"""
with Popen(*popenargs, **kwargs) as p:
try:
return p.wait(timeout=timeout)
except:
p.kill()
p.wait()
raise
Using call
:
import os
from subprocess import call
from shlex import split
try:
directoryListing = os.listdir(inputDirectory)
for infile in directoryListing:
meshlabString = #string to pass to command line
call(split(meshlabString)) # use split(str) to split string into args
except WindowsError as winErr:
print("Directory error: " + str((winErr)))
Upvotes: 1
Reputation: 309821
with subprocess, you have a few options. The easiest is call:
import shlex
return_code=subprocess.call(shlex.split(meshlabString))
shlex takes the string and splits it into a list the way the shell would split it. in other words:
shlex.split("this 'is a string' with 5 parts") # ['this', 'is a string', 'with', '5', 'parts]
You could also do:
return_code=subprocess.call(meshlabString,shell=True)
but this way is a security risk if meshlabString is untrusted. Ultimately, subprocess.call
is just a wrapper on the subprocess.Popen
class, provided for convenience, but it has the functionality that you want here.
Upvotes: 1