Q: My media converter app crashes when handling file names with spaces I wrote an app that uses ffmpeg to convert media files (.wav, .avi, .mp3, ... etc.). It works only with file names that have no spaces. When a file name with spaces is encountered, the app immediately closes. Can someone tell me if the string I'm using to call ffmpeg is correct, or need some characters escaped? Below is a fragment of the code:
...
...
...

#Select Media
os.chdir("c:\\d-Converter\\ffmpeg\\bin")
wrkdir = os.getcwd()
filelist = os.listdir(wrkdir)
self.formats1 = []

for filename in filelist:
    (head, filename) = os.path.split(filename)
    if filename.endswith(".avi") or filename.endswith(".mp4") or filename.endswith(".flv") or filename.endswith(".mov") or filename.endswith(".mpeg4") or filename.endswith(".mpeg") or filename.endswith(".mpg2") or filename.endswith(".wav") or filename.endswith(".mp3"):
            self.formats1.append(filename)
    self.format_combo1=wx.ComboBox(panel, size=(140, -1),value='Select Media', choices=self.formats1, style=wx.CB_DROPDOWN, pos=(300,50))

    self.Bind(wx.EVT_COMBOBOX, self.fileFormats, self.format_combo1)


...
...
...


def fileFormats(self, e):
    myFormats = {'audio': ('Select Format','.mp3', '.ogg', '.wav', '.wma'), 'video': ('Select Format','.flv','.mpg', '.mp4', '.mpeg')}
    bad_file = ['Media not supported']
    myFile = self.format_combo1.GetValue()
    f_exten = (x for x in myFormats['audio'] + myFormats['video'] if myFile.endswith(x))
    extension = f_exten.next()

    if extension in myFormats['audio']:
        self.format_combo2.SetItems(myFormats['audio'])

    elif extension in myFormats['video']:
        self.format_combo2.SetItems(myFormats['video'])
    else:
        self.format_combo2.SetItems(bad_file)
...
...
...


def convertButton(self, e):

    unit1 = self.format_combo1.GetValue()
    if unit1:
        unit1 = self.repl_Wspace(unit1)

    #Media Formats
    unit2 = self.format_combo2.GetValue()
    unit3 = self.format_combo3.GetValue()
    unit4 = None
    unit5 = self.format_combo5.GetValue()
    bitRate = self.format_combo6.GetValue()
    unit6 = bitRate
    if unit3 == '-qmax':
        unit4 = self.format_combo4.GetValue()
    else:
        pass

    os.chdir("c:\\d-Converter\\ffmpeg\\bin")
    wrkdir = os.getcwd()

    newfile = unit1
    stripped = newfile.strip('mpeg3aviovfl4w2c.') #Strips the extension from the original file name


    progname='c:\\d-Converter\\ffmpeg\\bin\\ffmpeg.exe' + ' -i '

    preset1_a='-vn -ar 44100 -ac 2 -ab'
    preset1_b='-f mp3 '
    preset_mp3='.mp3'

    chck_unit1 = self.my_endswith(unit1)



    while True:    
        if unit5 == 'video to mp3':

            if unit6 == 'k/bs' or unit6 == '':
                amsg = wx.MessageDialog(None, 'You must select a bit rate.', 'Media Converter', wx.ICON_INFORMATION)
                amsg.ShowModal()
                amsg.Destroy()
                break

            elif unit5 == 'video to mp3' and unit6 != 'k/bs' or unit6 != '':
                self.button.Disable()
                self.button2.Enable()
                self.format_combo1.Disable()
                self.format_combo2.Disable()
                self.format_combo3.Disable()
                self.format_combo4.Disable()
                self.format_combo5.Disable()
                self.format_combo6.Disable()
                startWorker(self.LongTaskDone, self.LongTask3, wargs=(progname, wrkdir, unit1, preset1_a, unit6, preset1_b, stripped, preset_mp3))
                break
            elif unit1 != unit1.endswith(".mpg") or unit1.endswith(".mpeg") or unit1.endswith(".avi") or unit1.endswith(".mp4") or unit1.endswith(".flv"):
                bmsg = wx.MessageDialog(None, 'You must select a valid format to convert to .mp3.', 'Media Converter', wx.ICON_INFORMATION)
                bmsg.ShowModal()
                bmsg.Destroy()
                break

        else:
            pass



        if unit1 == 'Select Media' or unit1 == '':
            amsg = wx.MessageDialog(None, 'You must select a media file!', 'Media Converter', wx.ICON_INFORMATION)
            amsg.ShowModal()
            amsg.Destroy()
            break


        elif unit2 == 'Select Format' or unit2 == '' or unit2 == chck_unit1:
            amsg = wx.MessageDialog(None, 'You must select a valid format', 'Media Converter', wx.ICON_INFORMATION)
            amsg.ShowModal()
            amsg.Destroy()
            break


        elif unit3 == 'Select Quality' or unit3 == '':
            amsg = wx.MessageDialog(None, 'You must select quality', 'Media Converter', wx.ICON_INFORMATION)
            amsg.ShowModal()
            amsg.Destroy()
            break

        elif unit3 != 'Select Quality' or unit3 != '':
            self.format_combo5.Disable()

            if unit3 == '-qmax':
                if unit4 == '0' or unit4 == '':
                    amsg = wx.MessageDialog(None, 'You must select number between 1-8.', 'Media Converter', wx.ICON_INFORMATION)
                    amsg.ShowModal()
                    amsg.Destroy()
                    break
                else:
                    self.button.Disable()
                    self.button2.Enable()
                    self.format_combo1.Disable()
                    self.format_combo2.Disable()
                    self.format_combo3.Disable()
                    self.format_combo4.Disable()
                    self.format_combo5.Disable()
                    startWorker(self.LongTaskDone, self.LongTask2, wargs=(progname,wrkdir,unit1,unit3,unit4,stripped,unit2))
                    break
            elif unit3 == '-sameq':
                self.button.Disable()
                self.button2.Enable()
                self.format_combo1.Disable()
                self.format_combo2.Disable()
                self.format_combo3.Disable()
                self.format_combo4.Disable()
                self.format_combo5.Disable()
                startWorker(self.LongTaskDone, self.LongTask, wargs=(progname,wrkdir,unit1,unit3,stripped,unit2))
                break   




def LongTask(self, progname, wrkdir, unit1, unit3, stripped, unit2):
    convert_file1 = progname + wrkdir + '\\' + unit1 + ' ' + unit3 + ' ' + stripped + unit2
    self.statusbar.SetStatusText("Converting: " + unit1 + "...")
    os.system(convert_file1)
    print convert_file1


def LongTask2(self, progname, wrkdir, unit1, unit3, unit4, stripped, unit2):
    convert_file2 = progname + wrkdir + '\\' + unit1 + ' ' + unit3 + ' ' + unit4 + ' ' + stripped + unit2
    self.statusbar.SetStatusText("Converting: " + unit1 + "...")
    os.system(convert_file2)

...
...
...


A: Don't use os.system to execute your command.  Instead, use subprocess, with each of your arguments as a separate entry in the arguments list:
import subprocess
progname='c:\\d-Converter\\ffmpeg\\bin\\ffmpeg.exe'
subprocess.check_call([progname, '-i', ... other args here])

This will ensure your arguments aren't interpreted incorrectly, and aren't susceptible to injection attacks.
