1 回答
TA贡献1883条经验 获得超3个赞
您需要单引号的原因是为了防止 shell 对您的参数进行任何扩展。这是一个问题,只有在使用shell=True. 如果未设置,shell 将永远不会触及您的参数,也无需“保护”它们。
然而,shell 也负责stdout重定向(即[... '>', output_json])。不使用 shell,需要在 Python 代码中处理重定向。然而,这就像将参数添加stdout=...到Popen.
总而言之,这意味着您的代码可以重写为
import os
import subprocess
# Still define first command line argument with triple quotes for readability
# Note that there are no single quotes though
jq_filter = """INDEX(.images[]; .id) as $imgs | {
"filename_with_label" : [
.annotations[]
| select(.attributes.type=="letter" )
| $imgs[.image_id] + {label:.text}
| {id:.id} + {filename:.file_name} + {label:.label} ] }"""
input_json_files = ["image_data_annotation.json"]
output_json_files = []
for input_json in input_json_files:
print("Processing %s" % (input_json))
filename, ext = os.path.splitext(input_json)
output_json = filename + "_with_label" + ext
output_json_files.append(output_json)
print("output file is : %s" % (output_json))
# Keep command as list, since this is what we need when NOT using shell=True
# Note also that the redirect and the output file are not parts of the argument list
jq_command = ['jq', jq_filter, input_json]
# shell keyword argument should NOT be set True
# Instead redirect stdout to an out_file
# (We must open the file for writing before redirecting)
with open(output_json, "w") as out_file:
subprocess.Popen(jq_command, stdout=out_file)
通常建议不要使用shell=True,因为这会打开另一个针对代码的攻击向量,因为注入攻击可以完全访问 shell。此外,不使用 shell 的另一个小好处是,它将减少创建的子进程的数量,因为不需要额外的 shell 进程。
添加回答
举报