Passing double quote shell commands in python to subprocess.Popen()?

前端 未结 5 397
自闭症患者
自闭症患者 2020-11-29 05:34

I\'ve been trying to pass a command that works only with literal double quotes in the commandline around the "concat:file1|file2" argument for ffmpeg.

相关标签:
5条回答
  • 2020-11-29 06:12

    I have been working with a similar issue, with running a relatively complex command over ssh. It also had multiple double quotes and single quotes. Because I was piping the command through python, ssh, powershell etc.

    If you can instead just convert the command into a shell script, and run the shell script through subprocess.call/Popen/run, these issues will go away.

    So depending on whether you are on windows or on linux or mac, put the following in a shell script either (script.sh or script.bat)

    ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4
    

    Then you can run

    import subprocess; subprocess.call(`./script.sh`; shell=True)
    

    Without having to worry about single quotes, etc.

    0 讨论(0)
  • 2020-11-29 06:18

    Either use single quotes 'around the "whole pattern"' to automatically escape the doubles or explicitly "escape the \"double quotes\"". Your problem has nothing to do with Popen as such.

    Just for the record, I had a problem particularly with a list-based command passed to Popen that would not preserve proper double quotes around a glob pattern (i.e. what was suggested in the accepted answer) under Windows. Joining the list into a string with ' '.join(cmd) before passing it to Popen solved the problem.

    0 讨论(0)
  • 2020-11-29 06:19

    I'd suggest using the list form of invocation rather than the quoted string version:

    command = ["ffmpeg", "-i", "concat:1.ts|2.ts", "-vcodec", "copy",
               "-acodec", "copy", "temp.mp4"]
    output,error  = subprocess.Popen(
                        command, universal_newlines=True,
                        stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
    

    This more accurately represents the exact set of parameters that are going to be passed to the end process and eliminates the need to mess around with shell quoting.

    That said, if you absolutely want to use the plain string version, just use different quotes (and shell=True):

    command = 'ffmpeg -i "concat:1.ts|2.ts" -vcodec copy -acodec copy temp.mp4'
    output,error  = subprocess.Popen(
                        command, universal_newlines=True, shell=True,
                        stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
    
    0 讨论(0)
  • 2020-11-29 06:19

    Also struggling with a string argument containing spaces and not wanting to use the shell=True.

    The solution was to use double quotes for the inside strings.

    args = ['salt', '-G', 'environment:DEV', 'grains.setvals', '{"man_version": "man-dev-2.3"}']
    
    try:
        p = subprocess.Popen(args, stdin=subprocess.PIPE
                                 , stdout=subprocess.PIPE
                                 , stderr=subprocess.PIPE
                            )
        (stdin,stderr) = p.communicate()
    except (subprocess.CalledProcessError, OSError ) as err:
        exit(1)
    if p.returncode != 0:
        print("Failure in returncode of command:")
    
    0 讨论(0)
  • 2020-11-29 06:30

    This works with python 2.7.3 The command to pipe stderr to stdout has changed since older versions of python:

    Put this in a file called test.py:

    #!/usr/bin/python
    import subprocess
    
    command = 'php -r "echo gethostname();"'
    p = subprocess.Popen(command, universal_newlines=True, shell=True, 
    stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    text = p.stdout.read()
    retcode = p.wait()
    print text
    

    Invoke it:

    python test.py
    

    It prints my hostname, which is apollo:

    apollo
    

    Read up on the manual for subprocess: http://docs.python.org/2/library/subprocess.html

    0 讨论(0)
提交回复
热议问题