我用subprocess模块调用不同的进程.但是,我有一个问题.
在以下代码中:
callProcess = subprocess.Popen(['ls', '-l'], shell=True)
Run Code Online (Sandbox Code Playgroud)
和
callProcess = subprocess.Popen(['ls', '-l']) # without shell
Run Code Online (Sandbox Code Playgroud)
两者都有效.阅读文档后,我开始知道这shell=True意味着通过shell执行代码.这意味着在缺席的情况下,该过程将直接启动.
那么我应该更喜欢我的情况 - 我需要运行一个进程并获得其输出.从shell内部或外部调用它有什么好处.
我正在寻找一种将包含双引号的参数传递给python的子进程模块的方法,而不会将双引号转义。
当引号围绕arg时,我已经看到过几次不同的问题,但是答案通常是删除引号。我遇到的问题是引号是参数的一部分,必须传递给脚本,而不必在每个引号前加反斜杠
例:
我正在调用subprocesTest.bat,这是一个简单的批处理脚本,它接受一个参数并回显它:
echo "%~1"
Run Code Online (Sandbox Code Playgroud)
我使用包含引号的arg从python调用批处理脚本:
import subprocess
test_string = 'Bill said "Hi!"'
cmd = ["subprocesTest.bat",
test_string
]
p = subprocess.Popen(cmd)
p.wait()
Run Code Online (Sandbox Code Playgroud)
预期输出:
“比尔说:“嗨!”
实际输出:
“比尔说\“嗨!\”
从命令行调用相同的批处理脚本时,我可以得到预期的输出,如下所示:
subprocesTest.bat“比尔说”嗨!“
查看源代码,subprocess.py的list2cmdline函数记录为:
3) A double quotation mark preceded by a backslash is
interpreted as a literal double quotation mark.
Run Code Online (Sandbox Code Playgroud)
但是,如果我逐步执行此功能,则看不到不加反斜杠就不能传递双引号的方法:
elif c == '"':
# Double backslashes.
result.append('\\' * len(bs_buf)*2)
bs_buf = []
result.append('\\"')
Run Code Online (Sandbox Code Playgroud)
所以我有两个问题...
这是询问此问题的其他线程,并且通过不使用引号来解决:
我实际上想在引数中使用引号的情况下,我看不到任何回应
我知道以前曾问过类似的问题,但它们似乎都是通过重新设计参数的传递方式(即使用列表等)来解决的。
但是,我这里有一个问题,因为我没有这个选项。有一个特定的命令行程序(我使用的是 Bash shell),我必须向其传递带引号的字符串。它不能不被引用,也不能有重复的参数,它只能是单引号或双引号。
command -flag 'foo foo1'
Run Code Online (Sandbox Code Playgroud)
我不会用command -flag foo foo1,也不会用command -flag foo -flag foo1。我认为这是命令接收输入方式的疏忽,但我无法控制它。
我传递参数如下:
self.commands = [
self.path,
'-flag1', quoted_argument,
'-flag2', 'test',
...etc...
]
process = subprocess.Popen(self.commands, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
results = process.communicate(input)
Run Code Online (Sandbox Code Playgroud)
哪里quoted_argument有像“foo foo1 foo2”这样的东西。我尝试转义单引号 ( "\'foo foo1 foo2\'"),但没有得到任何输出。
我知道这被认为是不好的做法,因为它解释起来不明确,但我没有其他选择。有任何想法吗?
我有一个 AWS S3 存储桶,其中填充了按日期参数化的数据。我想使用 AWS CLI(参考)(特别是命令)一次提取一个日期的数据aws s3 sync。
以下命令执行我期望的操作:
aws s3 sync s3://my-bucket-1 . --exclude "*" --include "*2018-01-17*" --dryrun
从命令行运行此命令会(dryrun) download为存储桶中包含子字符串的每个文件生成一个2018-01-17.
伟大的!为了简化必要的文件操作,我围绕这个执行器编写了一个小型 CLI 包装器。该包装器采用 Python 编写,并使用该subprocess.run工具来完成其工作。整个操作归结为以下调用:
subprocess.run(['aws', 's3', 'sync', 's3://my-bucket-1', '.', '--exclude', '"*"', '--include', '"*2018-01-17*"', '--dryrun'])
Run Code Online (Sandbox Code Playgroud)
问题是,当我运行此语句时,我会返回(dryrun) download存储桶中的每个文件。也就是说,返回与 01-18、01-19 等存储桶条目相对应的数据。--exclude/规则--include无法应用,结果与我简单运行的结果相同aws s3 sync s3://my-bucket-1 .
为什么会出现这种情况?