Search code examples
pythonpython-3.xsubprocessconvertersgif

How to properly execute a convert command using Python


I'm new to Python, so, I'm sorry if my question may seems dumb.

I'm trying to convert GIF files to APNG using this tool.

As it says in the bottom of this page, to convert GIF to APNG you must execute the following command:

$ vertopal convert GIF_INPUT_FILE --to apng

It works fine when I run the command in the terminal, but I cannot implement it in my Python code.

Here is my code:

import subprocess

discord_sticker_converter = subprocess.call("vertopal convert funny cat.gif --to apng")
print(discord_sticker_converter)

This is what is printed in the output:

usage: vertopal [options] <command> [<args>]
vertopal: error: unrecognized arguments: cat.gif
2

How should I call the convert command properly?


Solution

  • Let's talk about your command:

    "vertopal convert funny cat.gif --to apng"
    

    The name "funny cat.gif" has space in it. subprocess calls shlex.split() to split this string into a list of string tokens and the result is:

    >>> shlex.split("vertopal convert funny cat.gif --to apng")
    ['vertopal', 'convert', 'funny', 'cat.gif', '--to', 'apng']
    

    As you can see, the file name is broken into 2 tokens: "funny" and "cat.gif". That is why it failed. To fix this situation, you need to properly quote your file name:

    >>> shlex.split("vertopal convert 'funny cat.gif' --to apng")
    ['vertopal', 'convert', 'funny cat.gif', '--to', 'apng']
    

    The function subprocess.call() is flexible: it can take a single string and try to split it, or it can take a list of strings. That means both of these will work:

    subprocess.call("vertopal convert 'funny cat.gif' --to apng")
    subprocess.call(['vertopal', 'convert', 'funny cat.gif', '--to', 'apng'])
    

    The first form is more compact and is what you would do in the terminal. The second form is more explicit. Which form to use is your choice. As for me, I will choose the second form because the Zen of python said

    Explicit is better than implicit.