如何使用 popen 命令行参数包含单引号和双引号?

我想在 python3中运行以下jq命令。subprocess.Popen()


$ jq  '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}

     ]

   }' image_data_annotation.json > image_data_annotation_with_label.json

请注意,第一个命令行参数包含点、美元符号、单引号内的双引号。仅供参考,jq是用于处理 json 文件的 JSON 处理器实用程序。


我编写了以下 python3 脚本,用于使用jq实用程序自动处理 JSON 文件。


#!python3

# file name: letter_image_tool.py


import os, subprocess


"""

command line example to automate

$ jq  '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}

     ]

   }' image_data_annotation.json > image_data_annotation_with_label.json

"""


# define first command line argument

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))


    #jq_command ='jq' + " " +  jq_filter, input_json + ' > ' +  output_json

    jq_command =['jq', jq_filter,  input_json + ' > ' +  output_json]

    print(jq_command)

    subprocess.Popen(jq_command, shell=True)


第一个参数应该像上面的片段一样用单引号括起来,但我的脚本不处理它。


我认为主要问题与第一个命令行参数(jq_filter在上面的 python 脚本中)中使用的点、美元符号、单引号和双引号有关。但是我不知道如何处理这种与bash相关的复杂元字符。


我应该怎么做才能解决以上问题?


慕丝7291255
浏览 187回答 1
1回答

白板的微信

您需要单引号的原因是为了防止 shell 对您的参数进行任何扩展。这是一个问题,只有在使用shell=True. 如果未设置,shell 将永远不会触及您的参数,也无需“保护”它们。然而,shell 也负责stdout重定向(即[... '>', output_json])。不使用 shell,需要在 Python 代码中处理重定向。然而,这就像将参数添加stdout=...到Popen.总而言之,这意味着您的代码可以重写为import osimport subprocess# Still define first command line argument with triple quotes for readability# Note that there are no single quotes thoughjq_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 进程。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python