subprocess.call使用字符串vs使用列表

问题描述 投票:30回答:1

我正在尝试将rsync与subprocess.call一起使用。奇怪的是,如果我传递subprocess.call一个字符串,它可以工作,但是它不能用于列表(ala,Python的文档)。

使用字符串呼叫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

使用列表进行通话:

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)    

但是我想了解subprocess如何理解列表和字符串。

setting 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和一个字符串

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
python subprocess
1个回答
36
投票

[subprocess的用于处理命令参数的规则实际上有点复杂。

来自the docs

args应该是程序参数的序列,或者是单个字符串。默认情况下,如果args是序列,则要执行的程序是args中的第一项。如果args是字符串,则解释为platform-dependent,并在下面进行说明。有关默认行为的其他差异,请参见shellexecutable参数。 除非另有说明,否则建议将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环境变量指定默认外壳程序。在Windows上唯一需要指定shell=True的时间是将要执行的命令内置到Shell中(例如dircopy)。您不需要shell=True运行批处理文件或基于控制台的可执行文件。

(所有重点都是我的)

© www.soinside.com 2019 - 2024. All rights reserved.