使用 shell=True w/list 时忽略 subprocess.call() 参数[重复]

2025-02-25 09:09:00
admin
原创
34
摘要:问题描述:我正在尝试让 python 的 subprocess.call 方法通过列表(由一系列字符串组成)接受一些 args 命令,如 python 文档中建议的那样。为了在将其放入实际脚本之前探索此行为,我打开了 IPython,运行了一些涉及不同 shell 设置和 args 命令组合的命令,并得到了以...

问题描述:

我正在尝试让 python 的 subprocess.call 方法通过列表(由一系列字符串组成)接受一些 args 命令,如 python 文档中建议的那样。为了在将其放入实际脚本之前探索此行为,我打开了 IPython,运行了一些涉及不同 shell 设置和 args 命令组合的命令,并得到了以下行为:

In [3]: subprocess.call(['ls', '-%sl' %'a'])
total 320
drwxr-xr-x  20 Kohaugustine  staff   680 Oct 15 16:55 .
drwxr-xr-x   5 Kohaugustine  staff   170 Sep 12 17:16 ..
-rwxr-xr-x   1 Kohaugustine  staff  8544 Oct 15 16:55 a.out
-rwxr-xr-x   1 Kohaugustine  staff  8544 Oct  3 10:28 ex1-6
-rw-r--r--@  1 Kohaugustine  staff   204 Oct  3 10:28 ex1-6.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Oct  3 10:15 ex1-7
-rw-r--r--@  1 Kohaugustine  staff    71 Oct  3 10:15 ex1-7.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:22 hello
-rw-r--r--@  1 Kohaugustine  staff    58 Sep 12 16:27 hello.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:24 hello.o
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:24 hello_1.o
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:27 hello_2.o
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:27 hello_3.o
-rwxr-xr-x   1 Kohaugustine  staff  8544 Oct 15 16:55 lesson_1-5
-rw-r--r--@  1 Kohaugustine  staff   185 Sep 28 10:35 lesson_1-5.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 21 10:06 temperature.o
-rw-r--r--@  1 Kohaugustine  staff   406 Sep 21 09:54 temperature_ex1-3.c
-rw-r--r--@  1 Kohaugustine  staff   582 Sep 21 10:06 temperature_ex1-4.c
-rw-r--r--@  1 Kohaugustine  staff   178 Sep 23 17:21 temperature_ex1-5.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 23 17:21 temperature_ex1-5.o
Out[3]: 0

In [4]: subprocess.call(['ls', '-%sl' %'a'], shell=True)
a.out           ex1-7           hello.c         hello_2.o       lesson_1-5.c            temperature_ex1-4.c
ex1-6           ex1-7.c         hello.o         hello_3.o       temperature.o           temperature_ex1-5.c
ex1-6.c         hello           hello_1.o       lesson_1-5      temperature_ex1-3.c     temperature_ex1-5.o
Out[4]: 0

In [6]: subprocess.call(['ls', '-al'])    
total 320
drwxr-xr-x  20 Kohaugustine  staff   680 Oct 15 16:55 .
drwxr-xr-x   5 Kohaugustine  staff   170 Sep 12 17:16 ..
-rwxr-xr-x   1 Kohaugustine  staff  8544 Oct 15 16:55 a.out
-rwxr-xr-x   1 Kohaugustine  staff  8544 Oct  3 10:28 ex1-6
-rw-r--r--@  1 Kohaugustine  staff   204 Oct  3 10:28 ex1-6.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Oct  3 10:15 ex1-7
-rw-r--r--@  1 Kohaugustine  staff    71 Oct  3 10:15 ex1-7.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:22 hello
-rw-r--r--@  1 Kohaugustine  staff    58 Sep 12 16:27 hello.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:24 hello.o
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:24 hello_1.o
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:27 hello_2.o
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 12 16:27 hello_3.o
-rwxr-xr-x   1 Kohaugustine  staff  8544 Oct 15 16:55 lesson_1-5
-rw-r--r--@  1 Kohaugustine  staff   185 Sep 28 10:35 lesson_1-5.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 21 10:06 temperature.o
-rw-r--r--@  1 Kohaugustine  staff   406 Sep 21 09:54 temperature_ex1-3.c
-rw-r--r--@  1 Kohaugustine  staff   582 Sep 21 10:06 temperature_ex1-4.c
-rw-r--r--@  1 Kohaugustine  staff   178 Sep 23 17:21 temperature_ex1-5.c
-rwxr-xr-x   1 Kohaugustine  staff  8496 Sep 23 17:21 temperature_ex1-5.o
Out[6]: 0

In [7]: subprocess.call(['ls', '-al'], shell = True)
a.out           ex1-7           hello.c         hello_2.o       lesson_1-5.c            temperature_ex1-4.c
ex1-6           ex1-7.c         hello.o         hello_3.o       temperature.o           temperature_ex1-5.c
ex1-6.c         hello           hello_1.o       lesson_1-5      temperature_ex1-3.c     temperature_ex1-5.o
Out[7]: 0

似乎每当 shell=True 时,输出似乎都与以下内容相同:

In [9]: subprocess.call(['ls'])
a.out           ex1-7           hello.c         hello_2.o       lesson_1-5.c            temperature_ex1-4.c
ex1-6           ex1-7.c         hello.o         hello_3.o       temperature.o           temperature_ex1-5.c
ex1-6.c         hello           hello_1.o       lesson_1-5      temperature_ex1-3.c     temperature_ex1-5.o
Out[9]: 0

我很困惑;当我设置 shell=True 时,'-a' 选项发生了什么?shell 没有读取它吗?我读过文档,它说当 shell=True 时,它​​意味着我指定的命令将通过 shell 执行,所以它应该意味着 ls -a 被输入到 shell 并由 shell 执行。那么为什么会出现 [4] 和 [7] 中的行为?此外,pydocs 并没有直接解释它(尽管它确实说明了当我们设置 shell=False 时 subpprocess 不会做什么);当我们让 shell=False 时它意味着什么?操作系统中是否会生成一个新进程而不需要 shell 实际控制它?

另外,在 [3] 和 [4] 中使用格式字符串可能看起来非常尴尬,这是因为在我的实际脚本中,我将使用 subprocess.call,我必须依赖这些格式字符串来替换适当的命令选项。我无法对某些命令行选项进行硬编码。使用纯字符串作为参数也是不可能的,因为在我的脚本中将有一个方法必须对命令执行列表操作。我不知道是否有更好的方法来解决这个问题,所以如果有人能提出不同的建议,那将非常有帮助。

非常感谢!


解决方案 1:

shell为 True 时,第一个参数将附加到["/bin/sh", "-c"]。如果该参数是列表,则结果列表为

["/bin/sh", "-c", "ls", "-al"]

也就是说,只有ls,而不是ls -al用作选项的参数-c-al用作第一个参数的是 shell 本身,而不是ls

当使用时shell=True,您通常只想传递一个字符串并让 shell 根据 shell 的正常分词规则对其进行拆分。

# Produces ["/bin/sh", "-c", "ls -al"]
subprocess.call("ls -al", shell=True)

就您而言,似乎您shell=True根本不​​需要使用。

解决方案 2:

当您使用shell=True列表时,额外的参数将传递给 shell 本身,而不是传递给在 shell 中运行的命令。然后可以从 shell 脚本中引用它们(传递为argv[0]$0,如$1、 等。

最简单的答案是“不要那样做”:如果您想传递一个列表,请不要使用shell=True;如果您想传递一个字符串,请始终使用shell=True


也就是说,可以以读取这些参数的方式形成命令。下面是一个违反我上述规则的示例——没有这个命令你就无法实现[*1]shell=True(并且executable='/bin/bash'要避免使用 bash for 依赖操作系统/bin/sh),因为它依赖于 bash 的内置版本printf(支持%q作为扩展):

subprocess.call([
    "printf '%q\\n' \"$0\" \"$@\"",
    'these strings are
',
    '"shell escaped" in the output from this command',
    "so that the output can *safely* be run through eval",
    "observe that no /tmp/owned file is created",
    "including when the output of this script is run by bash as code:"
    "$(touch /tmp/owned) \"$(touch /tmp/owned)\"",
    '$(touch /tmp/owned) \'$(touch /tmp/owned)\'',
], shell=True, executable='/bin/bash')

[*1] - 如果忽略这一点,可以使用/bin/bashas argv[0]with shell=False

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1300  
  华为IPD产品开发流程是一套先进且成熟的产品开发管理体系,对众多企业提升产品竞争力有着重要的借鉴意义。它涵盖多个关键要素,这些要素相互关联、相互作用,共同构建起高效、科学的产品开发流程。深入剖析其中的五个核心要素,能让我们更好地理解华为成功背后的产品开发逻辑,为企业的产品创新与发展提供有力的指导。市场管理市场管理是IP...
IPD框架   20  
  华为集成产品开发(IPD)体系作为一套先进的产品开发管理理念和方法,在华为的发展历程中发挥了至关重要的作用。在供应链管理领域,IPD同样展现出巨大的价值,深刻影响着企业的运营效率、产品质量以及市场竞争力。通过将IPD理念融入供应链管理,华为实现了从产品规划到交付的全流程优化,为企业的持续发展奠定了坚实基础。IPD对供应...
IPD集成产品开发流程   23  
  IPD(Integrated Product Development)项目管理作为一种先进的产品开发管理模式,旨在通过整合跨部门资源,实现产品的高效开发与上市。然而,在实际推行过程中,IPD项目管理面临着诸多风险,若处理不当,可能导致项目进度延迟、成本超支甚至项目失败。深入了解这些风险并制定有效的应对策略,对于保障IP...
华为IPD流程   19  
  华为作为全球知名的科技企业,其成功背后的管理模式备受关注。其中,IPD(集成产品开发)产品开发流程对华为的创新发展起到了至关重要的推动作用。IPD不仅仅是一种流程,更是一种先进的管理理念,它将产品开发视为一个系统工程,涵盖了从市场需求分析、产品规划、研发、生产到上市等多个环节,通过整合企业内外部资源,实现高效、协同的产...
IPD流程中PDCP是什么意思   19  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用