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

2025-02-13 08:35:00
admin
原创
43
摘要:问题描述:我正在尝试将 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1590  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1361  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   18  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   18  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   19  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用