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

2025-02-13 08:35:00
admin
原创
42
摘要:问题描述:我正在尝试将 rsync 与 subprocess.call 结合使用。奇怪的是,如果我向 subprocess.call 传递一个字符串,它就可以工作,但传递列表则不行。使用字符串调用 sp.call:In [23]: sp.call("rsync -av content/ writin...

问题描述:

我正在尝试将 rsync 与 subprocess.call 结合使用。奇怪的是,如果我向 subprocess.call 传递一个字符串,它就可以工作,但传递列表则不行。

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

使用列表调用 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

我使用列表的方式有什么问题?你会如何修复它?我需要列表,因为我想使用变量。当然我可以使用:

  sp.call("rsync -av "+Orig+" "+Dest, shell=True)    

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

设置 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

设置 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

解决方案 1:

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

一般来说,要运行外部命令,您应该使用shell=False并传递序列形式的参数。shell=True仅当需要使用 shell 内置命令或特定 shell 语法时才使用;shell=True正确使用与平台相关,如下所述。

来自文档:

args应为程序参数序列,否则应为单个字符串。默认情况下,如果为序列,则要执行的程序是序列中的第一个项argsargs如果args为字符串,则解释取决于平台,如下所述。请参阅shellexecutable参数以了解与默认行为的其他差异。除非另有说明,否则建议args以序列形式传递。如果shell为 True,则建议args以字符串而不是序列形式传递。

shell=False

在 Unix 上,如果args是字符串,则该字符串将被解释为要执行的程序的名称或路径。但是,这只有在没有向程序传递参数的情况下才能完成。

在 Windows 上,如果args是序列,它将按照在Windows 上将参数序列转换为字符串中描述的方式转换为字符串。这是因为底层CreateProcess()对字符串进行操作。

shell=True

在带有 的 Unix 上shell=True,shell 默认为/bin/sh。如果args是字符串,则该字符串指定要通过 shell 执行的命令。这意味着字符串的格式必须与在 shell 提示符下键入时完全相同。这包括例如用引号或反斜杠转义带有空格的文件名。如果 args 是序列,则第一项指定命令字符串,任何其他项将被视为 shell 本身的附加参数。

在带有 的 Windows 上shell=TrueCOMSPEC环境变量指定默认 shell。在 Windows 上,唯一需要指定的情况shell=True是您希望执行的命令内置于 shell 中(例如dircopy)。您不需要shell=True运行批处理文件或基于控制台的可执行文件。

(重点均由我强调)


为了完整起见,下面列出了 UNIX 系统上四个示例中发生的情况:

字符串shell=True

subprocess.call("rsync -av a/ b/", shell=True)将调用sh -c "rsync -av a/ b/",执行shell脚本rsync -av a/ b/;shell会将其解析为对带有参数的调用,,,,rsync因此-av它可以正常工作。a/`b/`

请注意,如果任何参数包含空格或特殊的 shell 字符,则需要手动转义,这是一种脆弱的方法。

列出shell=True

subprocess.call(["rsync", "-av", "a/", "b/"], shell=True)将调用sh -c "rsync" -av a/ b/,执行 shell 脚本rsync,将 $0 设置为-av,将 $1 设置为a/,将 $2 设置为b/。此 shell 脚本调用时rsync不带任何参数(忽略 $0、$1、$2),这就是您看到满屏帮助文本的原因。

实现此目的的一种方法是subprocess.call(['rsync "$@"', "rsync", "-av", "a/", "b/"], shell=True)。这将调用一个 shell 脚本,该脚本将参数传递给。请注意,需要设置的rsync虚拟额外参数(请注意 的扩展以 $1 开头)。这不是一个理想的解决方案,因此很少使用 序列。rsync`$0$@shell=True`

字符串shell=False

subprocess.call("rsync -av a/ b/")将尝试查找名为rsync -av a/ b/$PATH 的二进制文件。由于不存在这样的二进制文件,因此您会收到错误subprocess。使用字符串时无法向程序提供任何参数shell=False

列出shell=False

subprocess.call(["rsync", "-av", "a/", "b/"])调用rsync$PATH 上的二进制文件,传递rsync参数为 argv[0]、-avargv[1]、a/argv[2] 和b/argv[3]。无需对参数进行转义,因为它们会直接传递到execve系统调用。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用