[Tutor] os.system vs subprocess.Popen args problems

eryksun eryksun at gmail.com
Tue Sep 3 06:49:09 CEST 2013


On Mon, Sep 2, 2013 at 10:19 AM, learner404 <learner404 at gmail.com> wrote:
>
> I can't understand why the command below works with os.system but not with
> subprocess.Popen (on windows, recording video with FFMPEG.exe)
>
> cmd=('ffmpeg -f dshow -i video="%s" -f dshow -i audio="%s" -q 5 "%s"')%
> (videoinputName, audioinputName, videoFileOutput)
> os.system(cmd)
> *works*
>
> subprocess.Popen(["ffmpeg","-f","dshow","-i",'video="%s"'%videoinputName,
>   "-f","dshow","-i",'audio="%s"'%audioinputName,"-q","5",
>   "%s"%videoFileOutput])
> *don't work*
>>> [dshow @ 025984a0] Could not find video device.
>>> video="QuickCam Orbit/Sphere AF": Input/output error

Popen joins the list into a string, as required by Windows
CreateProcess(). It assumes the tokenizing rules used by Microsoft's C
runtime. If that assumption is wrong, just switch to using a string
instead of a list, with whatever custom quoting is required. I'd first
try it like this:

    args = ['ffmpeg',
            '-f', 'dshow', '-i', 'video=%s' % videoinputName,
            '-f', 'dshow', '-i', 'audio=%s' % audioinputName,
            '-q', '5', videoFileOutput]

Here's a simple script to print the raw command line, and also sys.argv.

test.py

    import sys
    from ctypes import *

    windll.kernel32.GetCommandLineW.restype = c_wchar_p

    print(windll.kernel32.GetCommandLineW())
    print(' '.join(sys.argv))


system() vs Popen():

    >>> exe = sys.executable

    >>> cmdstr = '%s test.py video="QuickCam Orbit"' % exe
    >>> os.system(cmdstr)
    C:\Python27\python.exe  test.py video="QuickCam Orbit"
    test.py video=QuickCam Orbit
    0

    >>> cmdlst = [exe, 'test.py', 'video="QuickCam Orbit"']
    >>> subprocess.call(cmdlst)
    C:\Python27\python.exe test.py "video=\"QuickCam Orbit\""
    test.py video="QuickCam Orbit"
    0

Automatic vs manual quoting:

    >>> cmdlst2 = [exe, 'test.py', 'video=QuickCam Orbit']
    >>> subprocess.call(cmdlst2)
    C:\Python27\python.exe test.py "video=QuickCam Orbit"
    test.py video=QuickCam Orbit
    0

    >>> subprocess.call(cmdstr)
    C:\Python27\python.exe test.py video="QuickCam Orbit"
    test.py video=QuickCam Orbit
    0

> The reason I'm going with subprocess is to avoid to have the DOS window
> coming in the forefront.
> Any idea of what I'm doing wrong? Or any other way to hide or minimize the
> DOS window?

The startupinfo option can hide the window, including a console window:

http://docs.python.org/2/library/subprocess.html#subprocess.STARTUPINFO

By the way, unless you're running Windows 9x, a console window isn't
"DOS". A console is hosted in a separate process (csrss.exe or
conhost.exe). Multiple processes can attach to a single console. If a
process doesn't create or inherit a console automatically, it can
attach to an existing one (kernel32.AttachConsole) or allocate one
manually (kernel32.AllocConsole).


More information about the Tutor mailing list