Search code examples
pythondecoratorshutilcontextmanagercpio

Python - Why Am I Seeing This Output?


So I'm getting into Python and I'm writing a script to:

  1. Download an RPM using urllib.urlretrieve.
  2. Extract the files using rpm2cpio and cpio.
  3. Do some stuff with the files.
  4. Clean up using shutil.rmtree.

Functionally it's all good it does do all of that but since I put in the clean up code I'm getting the following output:

rpm2cpio: MyRPM.rpm: No such file or directory
cpio: premature end of archive

Here is the code:

#!/usr/bin/python

from contextlib import contextmanager
import os, subprocess, shutil

@contextmanager
def cd(directory):
    startingDirectory = os.getcwd()
    os.chdir(os.path.expanduser(directory))
    try:
        yield
    finally:
        os.chdir(startingDirectory)

# Extract the files from the RPM to the temp directory
with cd("/tempdir"):
    rpm2cpio = subprocess.Popen(["rpm2cpio", "MyRPM.rpm"], stdout=subprocess.PIPE)
    cpio = subprocess.Popen(["cpio", "-idm", "--quiet"], stdin=rpm2cpio.stdout, stdout=None)

# Do
# Some
# Things
# Involving
# Shenanigans

# Remove the temp directory and all it's contents
shutil.rmtree("/tempdir")

If you see some syntax issues with the code here (or missing imports or something) please ignore unless it actually pertains to the reason I'm getting the two messages. I tried to strip down the script to the releveant bits. All I'm looking for is an explanation as to why the above two messages are being printed. I'd have assumed that the script is executed from the top down but now I'm thinking I may be wrong in this case?

EDIT: It feels like the 'rpm2cpio' and 'cpio' commands are leaving something open as long as the script is running like something I need to explicitly close...? Does that make any sense? :)

Thanks! J


Solution

  • subprocess.Popen is non-blocking, so you basically have a race condition - between your calls to Popen and rmtree there is no guarantee that those processes can finish (or even start!) before rmtree runs.

    I suggest you wait for the Popen objects to return with

    cpio.wait()
    rpm2cpio.wait()
    
    # Remove the temp directory and all it's contents
    shutil.rmtree("/tempdir")
    

    Using the blocking subprocess.call doesn't look like an option for you with how you're piping the commands.