如何将参数从命令行传递到 python 脚本以读取和更新 json 文件中存在的某些键的值

Posted

技术标签:

【中文标题】如何将参数从命令行传递到 python 脚本以读取和更新 json 文件中存在的某些键的值【英文标题】:How do I pass arguments from command line to the python script to read and update values of certain keys present in a json file 【发布时间】:2021-03-24 19:47:56 【问题描述】:

我在 json 文件中有某些数据(例如 example.json),

example.json

data = 
     'name'   :  'Williams',
     'working':  False,
     'college':  ['NYU','SU','OU'],
     'NYU'    :  
                  'student'  : True,
                  'professor': False,
                  'years'    : 
                                 'fresher'  : '1',
                                 'sophomore': '2',
                                 'final'    : '3'

                                

                   
   

我希望编写一个代码,其中我可以在命令行上给出参数,即假设如果脚本保存在文件“script.py”中,那么,

在终端中:如果我输入*$ python3* script.py --get name --get NYU.student 则输出name=Williams

NYU.student=True

如果我输入*$ python3* script.py' --set name=Tom --set NYU.student=False

然后,它将字典中的 name 和 NYU.student 键更新为 Tom 和 False,并在命令行上输出 NYU.student=TomNYU.student=False

我已经为 python 脚本尝试了以下代码(即 script.py)

script.py

import json
import pprint
import argparse


    if __name__== "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument("--get", help="first command")
    parser.add_argument("--set", help="second command")


    args=parser.parse_args()

    with open('example.json','r') as read_file:
        data=json.load(read_file)
    



    if args.set == None:
        key = ' '.join(args.get[:])
        path = key.split('.')
        now = data
        for k in path:
          if k in now:
            now = now[k]
          else:
            print('Error: Invalid Key')
        print(now)  
    elif args.get == Null:
        key, value = ' '.join(args.set[:]).split('=')
        path = key.split('.')
        now = data
        for k in path[:-1]:
            if k in now:
                now = now[k]
            else:
                print('Error: Invalid Key')
        now[path[-1]] = value



    with open('example.json','w') as write_file:    #To write the updated data back to the same file
            json.dump(data,write_file,indent=2)
    

但是,我的脚本没有按预期工作?请帮我写剧本

【问题讨论】:

请解释它是如何不工作的,或者你在运行它时遇到了什么错误。 我没有收到任何错误,但是它没有在屏幕上显示读取的值或更新的值 【参考方案1】:

为了使用命令行传递参数,请使用 python3 中的 sys 模块。 sys 模块将命令行参数读取为字符串列表。列表中的第一个元素始终是文件名,后续元素是 arg1、arg2 ..... 以此类推。

希望下面的例子有助于理解sys模块的使用。

示例命令:

python filename.py 1 thisisargument2 4

对应代码

import sys

# Note that all the command line args will be treated as strings
# Thus type casting will be needed for proper usage

print(sys.argv[0])
print(sys.argv[1])
print(sys.argv[2])
print(sys.argv[3])    

对应的输出

filename.py 
1 
thisisargument2 
4

另外,请在 *** 上发布问题之前进行彻底的谷歌搜索。

【讨论】:

sys模块与本题无关。 OP 正在使用 argparse 模块。请先了解问题,然后再在 *** 上发布答案。【参考方案2】:

您的代码存在以下问题:

    在第 23 行和第 35 行连接参数值时,使用空格。这导致“错误键”值。删除空格即可解决问题。
key = ''.join(arg[:])
    您将参数定义为只传递一个值。不是多个。因此,即使您传递多个 --get--set 值,脚本也只会获得一个值。在第 9 行和第 10 行添加 action="append" 即可解决此问题。
parser.add_argument("--get", help="first command", action="append")
parser.add_argument("--set", help="second command", action="append")

完整代码:

import json
import pprint
import argparse


if __name__== "__main__":
    parser = argparse.ArgumentParser()

    parser.add_argument("--get", help="first command", action="append")
    parser.add_argument("--set", help="second command", action="append")


    args=parser.parse_args()
    try:
        with open('example.json','r') as read_file:
            data=json.load(read_file)
    except IOError:
        print("ERROR: File not found")
        exit()
    
    if args.set == None:
        for arg in args.get:
            
            key = ''.join(arg[:])
            
            path = key.split('.')
            now = data
            for k in path:
              if k in now:
                now = now[k]
              else:
                print('Error: Invalid Key')
            print(f"arg = now")  
    elif args.get == None:
        for arg in args.set:
            key, value = ''.join(arg[:]).split('=')
            
            path = key.split('.')
            now = data
            for k in path[:-1]:
                if k in now:
                    now = now[k]
                else:
                    print('Error: Invalid Key')
            print(f"arg")
            now[path[-1]] = value
            



    with open('example.json','w') as write_file:    #To write the updated data back to the same file
            json.dump(data,write_file,indent=2)
   

【讨论】:

如何打印设置值?假设我输入,那么我需要在命令行中得到输出,这样我才能确认已经设置好了。 像这样添加print(f"arg = now") 您可以为此使用 Try except 块。我已经更新了我的代码。请检查。如果有帮助,请考虑批准答案:) 在您的脚本中,当密钥无效时,您已经使用了print() 语句。我认为您可以将其用于此目的 使用 Try except 块,ValueError 例外,例如:w3schools.com/python/python_try_except.asp【参考方案3】:

这里是问题的get部分,我希望你能继续你的作业的set部分。祝你好运

python test.py --get name NYU.student

import json
import pprint
import argparse

def match(data: dict, filter: str):
    current = data

    for f in filter.split("."):
        if f not in current:
            return False
        current = current[f]
    
    return current == True
    

if __name__== "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--get", nargs="*", help="first command")

    args = parser.parse_args()

    with open('example.json','r') as f:
        data = json.loads(f.read())

    if args.get is not None and len(args.get) == 2:
        attr_name = args.get[0]
        if match(data, args.get[1]):
            print("=".format(attr_name, data[attr_name]))


【讨论】:

以上是关于如何将参数从命令行传递到 python 脚本以读取和更新 json 文件中存在的某些键的值的主要内容,如果未能解决你的问题,请参考以下文章

shell脚本处理用户输入

shell脚本处理用户输入

使用 argparser 将参数传递给入口点 python 脚本

如何将命令行参数输入 Python Anywhere 的调度程序?

将参数从命令行传递到 tcl 脚本

如何从文件传递命令行参数