我正在尝试将rsync与subprocess.call一起使用。奇怪的是,如果我传递subprocess.call一个字符串,它可以工作,但它不适用于列表(ala,Python的doc)。
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
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
我如何使用列表有什么问题?你会怎么解决它?我需要列表,因为我想使用变量。我当然可以使用:
sp.call("rsync -av "+Orig+" "+Dest, shell=True)
但我想了解子进程如何理解列表与字符串。
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
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
答案 0 :(得分:33)
subprocess
处理命令参数的规则实际上有点复杂。
来自the docs:
args
应该是一系列程序参数或者是一个单独的字符串。默认情况下,如果args
是序列,则要执行的程序是args
中的第一项。如果args
是字符串,则解释依赖于平台,如下所述。有关与默认行为的其他差异,请参阅shell
和executable
参数。 除非另有说明,否则建议将args
作为序列传递....如果shell
为True,建议将args
作为字符串传递,而不是作为字符串传递序列强>
使用shell=False
:
在Unix上,如果
args
是一个字符串,则该字符串被解释为要执行的程序的名称或路径。但是,只有在不将参数传递给程序时才能执行此操作。在Windows上,如果
args
是一个序列,它将以Converting an argument sequence to a string on Windows中描述的方式转换为字符串。这是因为基础CreateProcess()
对字符串进行操作。
使用shell=True
:
在具有
shell=True
的Unix上,shell默认为/bin/sh
。如果args
是字符串,则字符串指定要通过shell执行的命令。这意味着字符串的格式必须与在shell提示符下键入时完全相同。这包括,例如,引用或反斜杠转义带有空格的文件名。 如果args是一个序列,第一个项目指定命令字符串,任何其他项目将被视为shell本身的附加参数。在
shell=True
的Windows上,COMSPEC
环境变量指定默认shell。您需要在Windows上指定shell=True
的唯一时间是您希望执行的命令内置到shell中(例如dir
或copy
)。您不需要shell=True
来运行批处理文件或基于控制台的可执行文件。
(所有强调我的)