Python subprocess.call 使用字符串与使用列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15109665/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
subprocess.call using string vs using list
提问by Oz123
I am trying to use rsync with subprocess.call. Oddly, it works if I pass subprocess.call a string, but it won't work with a list (ala, Python's doc).
我正在尝试将 rsync 与 subprocess.call 一起使用。奇怪的是,如果我传递 subprocess.call 一个字符串,它会起作用,但它不适用于列表(ala,Python 的文档)。
calling sp.call with a string:
用字符串调用 sp.call:
In [23]: sp.call("rsync -av content/ writings_raw/", shell=True)
sending incremental file list
sent 6236 bytes received 22 bytes 12516.00 bytes/sec
total size is 324710 speedup is 51.89
Out[23]: 0
calling sp.call with a list:
使用列表调用 sp.call:
In [24]: sp.call(["rsync", "-av", "content/", "writings_raw/"], shell=True)
rsync version 3.0.9 protocol version 30
Copyright (C) 1996-2011 by Andrew Tridgell, Wayne Davison, and others.
Web site: http://rsync.samba.org/
Capabilities:
64-bit files, 64-bit inums, 32-bit timestamps, 64-bit long ints,
socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace,
append, ACLs, xattrs, iconv, symtimes
rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you
are welcome to redistribute it under certain conditions. See the GNU
General Public Licence for details.
rsync is a file transfer program capable of efficient remote update
via a fast differencing algorithm.
Usage: rsync [OPTION]... SRC [SRC]... DEST
or rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
or rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST
or rsync [OPTION]... [USER@]HOST:SRC [DEST]
or rsync [OPTION]... [USER@]HOST::SRC [DEST]
or rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
The ':' usages connect via remote shell, while '::' & 'rsync://' usages connect
to an rsync daemon, and require SRC or DEST to start with a module name.
Options
-v, --verbose increase verbosity
-q, --quiet suppress non-error messages
--no-motd suppress daemon-mode MOTD (see manpage caveat)
... snipped....
repeated: --filter='- .rsync-filter'
--exclude=PATTERN exclude files matching PATTERN
--blocking-io use blocking I/O for the remote shell
-4, --ipv4 prefer IPv4
-6, --ipv6 prefer IPv6
--version print version number
(-h) --help show this help (-h is --help only if used alone)
...snipped ...
rsync error: syntax or usage error (code 1) at main.c(1438) [client=3.0.9]
Out[24]: 1
What is wrong with how I use the list? How would you fix it? I need the list, because I would like to use variables. Of course I could use:
我使用列表的方式有什么问题?你会怎么修?我需要这个列表,因为我想使用变量。我当然可以使用:
sp.call("rsync -av "+Orig+" "+Dest, shell=True)
But I would like to understand how subprocessunderstands lists vs. strings.
但我想了解如何subprocess理解列表与字符串。
setting shell=False and a list:
设置 shell=False 和一个列表:
In [36]: sp.call(['rsync', '-av', ORIG, DEST], shell=False)
sending incremental file list
sent 6253 bytes received 23 bytes 12552.00 bytes/sec
total size is 324710 speedup is 51.74
Out[36]: 0
setting shell=False and a string
设置 shell=False 和一个字符串
In [38]: sp.call("rsync -av"+" "+ORIG+" "+DEST, shell=False)
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-38-0d366d3ef8ce> in <module>()
----> 1 sp.call("rsync -av"+" "+ORIG+" "+DEST, shell=False)
/usr/lib/python2.7/subprocess.pyc in call(*popenargs, **kwargs)
491 retcode = call(["ls", "-l"])
492 """
--> 493 return Popen(*popenargs, **kwargs).wait()
494
495
/usr/lib/python2.7/subprocess.pyc in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
677 p2cread, p2cwrite,
678 c2pread, c2pwrite,
--> 679 errread, errwrite)
680
681 if mswindows:
/usr/lib/python2.7/subprocess.pyc in _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
1257 if fd is not None:
1258 os.close(fd)
-> 1259 raise child_exception
1260
1261
OSError: [Errno 2] No such file or directory
采纳答案by nneonneo
subprocess's rules for handling the command argument are actually a bit complex.
subprocess处理命令参数的规则实际上有点复杂。
From the docs:
从文档:
argsshould be a sequence of program arguments or else a single string. By default, the program to execute is the first item inargsifargsis a sequence. Ifargsis a string, the interpretation is platform-dependentand described below. See theshellandexecutablearguments for additional differences from the default behavior. Unless otherwise stated, it is recommended to passargsas a sequence.... Ifshellis True, it is recommended to passargsas a string rather than as a sequence.
args应该是一系列程序参数或单个字符串。默认情况下,要执行的程序是argsifargs序列中的第一项。如果args是字符串,则解释取决于平台,如下所述。有关shell与executable默认行为的其他差异,请参阅和参数。除非另有说明,建议args作为序列传递……如果shell为True,则建议args作为字符串传递,而不是作为序列传递。
With shell=False:
与shell=False:
On Unix, if
argsis a string, the string is interpreted as the name or path of the program to execute. However, this can only be done if not passing arguments to the program.On Windows, if
argsis a sequence, it will be converted to a string in a manner described in Converting an argument sequence to a string on Windows. This is because the underlyingCreateProcess()operates on strings.
在 Unix 上,如果
args是字符串,则该字符串被解释为要执行的程序的名称或路径。但是,这只能在不向程序传递参数的情况下完成。在 Windows 上,如果
args是序列,它将以在 Windows 上将参数序列转换为字符串中描述的方式转换为字符串。这是因为底层CreateProcess()对字符串进行操作。
With shell=True:
与shell=True:
On Unix with
shell=True, the shell defaults to/bin/sh. Ifargsis a string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself.On Windows with
shell=True, theCOMSPECenvironment variable specifies the default shell. The only time you need to specifyshell=Trueon Windows is when the command you wish to execute is built into the shell (e.g.dirorcopy). You do not needshell=Trueto run a batch file or console-based executable.
在带有
shell=True的Unix 上,shell 默认为/bin/sh. 如果args是字符串,则字符串指定要通过 shell 执行的命令。这意味着字符串的格式必须与在 shell 提示符下键入时完全相同。例如,这包括引用或反斜杠转义其中包含空格的文件名。如果 args 是一个序列,则第一项指定命令字符串,任何附加项都将被视为 shell 本身的附加参数。在带有
shell=True的Windows 上,COMSPEC环境变量指定默认 shell。您需要shell=True在 Windows上指定的唯一时间是您希望执行的命令已内置到外壳程序中(例如dir或copy)。您不需要shell=True运行批处理文件或基于控制台的可执行文件。
(all emphasis mine)
(全部强调我的)

