48a49,69 > .. warning:: > > Do not put the entire command into one string as your *args* when > *shell=False*, unless you're not giving the command any arguments at all:: > > >>> p1 = Popen(args="/home/arthur/print_args.py -input eggs.txt") > Traceback (most recent call last): > ... > OSError: [Errno 2] No such file or directory > >>> p2 = Popen(args=["/home/arthur/print_args.py -input eggs.txt"]) > Traceback (most recent call last): > ... > OSError: [Errno 2] No such file or directory > > Shell equivalent to these erroneous examples (note the quotes):: > $ '/home/arthur/print_args.py -input eggs.txt' > -sh: /home/arthur/print_args.py -input eggs.txt: No such file or directory > > Notice in these cases that the system is trying to execute a (nonexistent) > program whose name includes the entire command string, arguments and all. > 53a75,88 > .. note:: > > Determining the exact correct *args* value for a given shell command string > can be tricky, especially in complex cases. > :meth:`shlex.split` can be very helpful when trying to determine the correct > tokenization:: > > >>> import shlex, subprocess > >>> command_line = raw_input("Command line:") > /bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "python -c 'print __name__'" > >>> shlex.split(command_line) > ['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "python -c 'print __name__'"] > >>> p = subprocess.Popen(['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "python -c 'print __name__'"]) #Success! > 58a94,107 > .. warning:: > > When constructing a command string and using *shell=True*, be mindful of > escaping characters of special meaning to the shell:: > > >>> filename = "has some spaces" > >>> subprocess.Popen("rm "+filename, shell=True) #WRONG: deletes 3 files named "has", "some", and "spaces" > >>> subprocess.Popen("rm "+filename.replace(' ', r'\ '), shell=True) #CORRECT: deletes one file > >>> subprocess.Popen("rm "+('"%s"' % filename), shell=True) #ALSO CORRECT > >>> subprocess.Popen(["rm", filename], shell=False) #SAFER: Now you don't need to worry about the escaping > > This and similar pitfalls are why one should avoid using *shell=True* > whenever feasible. > 242a292,342 > An Illustrative Example > ^^^^^^^^^^^^^^^^^^^^^^^ > Determining the correct *args* for a given shell command string can be tricky. > Here, a worked example is presented to help get a feel for shell tokenization > and calling :class:`Popen`'s constructor. > > The following simple program can be used to empirically inspect the arguments > passed to it:: > > #!/usr/bin/env python > #print_args.py: Prints each of its command line arguments on a separate line, with index numbers > import sys > for index, arg in enumerate(sys.argv): > print ("%s:" % index), arg > > Here is a particularly complex shell command line invoking the program:: > > $ ./print_args.py -input eggs.txt -output "spam spam.txt" -cmd "python -c 'print __name__'" > 0: ./print_args.py > 1: -input > 2: eggs.txt > 3: -output > 4: spam spam.txt > 5: -cmd > 6: python -c 'print __name__' > > .. warning:: > > "-input" and "eggs.txt" are two separate arguments to the program, even > though one is the parameter of the other. For example, this would be wrong > (note the differing output):: > > >>> p = subprocess.Popen(["./print_args.py", "-input eggs.txt"]) > 0: ./print_args.py > 1: -input eggs.txt > > Here is the shell equivalent to illustrate the problem:: > > $ ./print_args.py '-input eggs.txt' > > The same applies to the other argument pairs. > > Here are equivalent ways to invoke the program with the same arguments as before:: > > >>> p1 = subprocess.Popen('./print_args.py -input eggs.txt -output "spam spam.txt" -cmd "python -c \'print __name__\'"', shell=True) > >>> p2 = subprocess.Popen('./print_args.py -input eggs.txt -output spam\\ spam.txt -cmd "python -c \'print __name__\'"', shell=True) > >>> p3 = subprocess.Popen(r'./print_args.py -input eggs.txt -output spam\ spam.txt -cmd "python -c \'print __name__\'"', shell=True) > >>> p4 = subprocess.Popen(["./print_args.py", "-input", "eggs.txt", "-output", "spam spam.txt", "-cmd", "python -c 'print __name__'"], shell=False) #MOST PREFERRED > > The last method, with *shell=False*, is the most recommended one. > 548d647 <