Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python to wait for shell command to complete

I am running script to unrar some files and the remove the rar files afterwards. I am doing this by running the command through shell. I have tried several different ways to make the script wait until it's done unpacking the files, but it still goes ahead and deletes the file before they are done being used.

I have tried the code below, which is a no go. I have tried to see if i could get the wait() to work, but also no luck.

Any ideas? running python 2.7

EDIT: I want the script to run the command :)

            p = subprocess.Popen('unrar e ' + root + '/' + i + ' ' + testfolder,
                                 bufsize=2048, shell=True,
                                 stdin=subprocess.PIPE)
            p.stdin.write('e')
            p.communicate()

for root, dirs, files in os.walk(testfolder):
    for i in files:

        print 'Deleting rar files'
        os.remove(i)

for i in os.listdir(testfolder):
    if os.path.isdir(testfolder + i):
        shutil.rmtree(testfolder + i)
like image 318
Dennis Olsen Avatar asked Apr 24 '13 15:04

Dennis Olsen


People also ask

How do you run a shell command in Python?

If you need to execute a shell command with Python, there are two ways. You can either use the subprocess module or the RunShellCommand() function. The first option is easier to run one line of code and then exit, but it isn't as flexible when using arguments or producing text output.

How do I run a shell command in Python using subprocess?

Python Subprocess Run Function The subprocess. run() function was added in Python 3.5 and it is recommended to use the run() function to execute the shell commands in the python program. The args argument in the subprocess. run() function takes the shell command and returns an object of CompletedProcess in Python.

How do you run a shell command from Python and get the output?

In Python 3.5+, check_output is equivalent to executing run with check=True and stdout=PIPE , and returning just the stdout attribute. You can pass stderr=subprocess. STDOUT to ensure that error messages are included in the returned output.

Does subprocess run wait for finish?

subprocess. run() is synchronous which means that the system will wait till it finishes before moving on to the next command.


1 Answers

This is evil:

p = subprocess.Popen('unrar e ' + root + '/' + i + ' ' + testfolder,
        bufsize=2048, shell=True, stdin=subprocess.PIPE)

Instead,

p = subprocess.Popen(['unrar', 'e', '%s/%s' % (root, i), testfolder],
        bufsize=2048, stdin=subprocess.PIPE)
p.stdin.write('e')
p.wait()
if p.returncode == 0:
    pass # put code that must only run if successful here.

By passing an exact array rather than a string to Popen and not using shell=True, a filename with a space in it can't be interpreted as a more than one arguments, or a subshell command, or some other potentially malicious thing (think of a file with $(rm -rf ..) in its name).

Then, after calling p.wait() (there's no need for p.communicate() when you aren't capturing stderr or stdout), you must check p.returncode to determine whether the process was successful, and only proceed on to delete files if p.returncode == 0 (indicating success).

Your initial diagnosis, that p.communicate() is returning while the unrar process is still running, is not feasible; p.communicate() and p.wait() do not work that way.


If running across ssh, this changes a bit:

import pipes # in Python 2.x; in 3.x, use shlex.quote() instead
p = subprocess.Popen(['ssh', ' '.join(
      [pipes.quote(s) for s in ['unrar', 'e', '%s/%s' % (root, i), testfolder]])
like image 165
Charles Duffy Avatar answered Sep 16 '22 12:09

Charles Duffy