Search code examples
pythonpython-2.7unixsubprocessattributeerror

What causes "AttributeError: 'tuple' object has no attribute 'rfind'" when I attempt to use subprocess.call


I'm trying to write a function that will walk through a series of subfolders from a given path and unzip all the files within it that end in a .fastq.gz and leaves the others alone.

I'm aware that there are other ways to go about this but I'm having the same error message for some more complex code later on in my program that relies on the same principle, and I figured this would be a better example.

def unzipdir(path):#walks through folders in the listed path and unzips files
    for root, dirs, files in os.walk(path):
        for name in files:              
            if name.endswith((".fastq.gz")):
                filepath = os.path.join(root, name)
                x = "gzip ", "-d ", "{kwarg}".format(kwarg=filepath)
                print([x])
                subprocess.call([x])
                subprocess.call("exit 1", shell=True)

error message...

$ ./test.py
[('gzip ', '-d ', '/nobackup/example/working/examplefile.fastq.gz')]
Traceback (most recent call last):
    File "./test.py", line 76, in <module>
        unzipdir('/nobackup/example/working')
    File "./test.py", line 23, in unzipdir
        subprocess.call([x])
    File "/usr/lib64/python2.6/subprocess.py", line 478, in call
        p = Popen(*popenargs, **kwargs)
    File "/usr/lib64/python2.6/subprocess.py", line 642, in __init__
        errread, errwrite)
    File "/usr/lib64/python2.6/subprocess.py", line 1238, in _execute_child
        raise child_exception
    AttributeError: 'tuple' object has no attribute 'rfind'

Any help would really be appreciated as I'm having trouble tracking down the cause of my error.

Many thanks.


Solution

  • The first argument to subprocess.call should be an iterable (list, tuple, etc.) of arguments, and each argument must be a string. In subprocess.call([x]), based on the print above, we can see that x is a tuple of strings; thus, you are passing subprocess.call a list of tuples of strings rather than an iterable of strings. Simply call subprocess.call(x) instead (or, if you're insistent on passing a list, subprocess.call(list(x))).