使用 Argparse 进行字典

Posted

技术标签:

【中文标题】使用 Argparse 进行字典【英文标题】:Using Argparse for Dictionary 【发布时间】:2018-01-04 11:46:42 【问题描述】:

我想阅读视频列表中的任何一项。视频读取和显示代码如下。这段代码运行良好。

import cv2


def VideoReading(vid):

    cap = cv2.VideoCapture(vid)
    while True:
        ret, frame = cap.read()
        cv2.imshow('Video', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()

由于我有大量视频,并且我通过命令行调用代码,因此编写整个视频名称很麻烦。所以我创建了一个字典。这里给出2的例子:

"Video1.mp4": 1, 'Video2.mp4': 2

现在我使用以下代码调用视频,使用值 1 或 2,而不是视频名称。代码如下:

def Main():

    VideoFiles= ["Video1.mp4", "Video2.mp4"]
    VideoFilesIndicator = [1, 2]

    model_list = 
    for i in range(len(VideoFiles)):
        model_list[VideoFiles[i]] = VideoFilesIndicator[i]

    print(model_list)
    def convertvalues(value):
        return model_list.get(value, value)

    parser = argparse.ArgumentParser()
    group = parser.add_mutually_exclusive_group()


    group.add_argument("-v", "--video", help = "add video file name of any format", type = convertvalues,\
                     choices = [1,2], default = 1)

    args =parser.parse_args()

    return VideoReading(args.video)



if __name__ == "__main__":

    Main()

现在当我在 cmd "python VideoReading.py -v 2" 中运行代码时,它会抛出以下错误。

错误:参数 -v/--video:无效选择:'2'(从 1、2 中选择)

我不明白为什么会出现此错误。我正在关注this 的帖子来构建我的程序。

【问题讨论】:

VideoReading(args.video)中抛出错误?如果是这样,您可以尝试对其进行调整以返回 VideoReading(int(args.video)) 吗? @Uvar:我已经试过了。但仍然遇到同样的问题。 model_list = dict(zip(VideoFilesIndicator, VideoFiles));请注意您的字典目前是倒退的;您想将数字映射到文件名,反之亦然。 强制程序用户知道文件的内部编号是糟糕的界面设计。 @chepner:感谢您的建议。我知道,但我的经理建议我这样做! 【参考方案1】:

问题在于convertvalues'2' 作为字符串返回,因为convertvaluesmodel_list 中找不到它时会按原样返回value(即字符串)。尝试:

def convertvalues(value):
    return model_list.get(value, int(value))

同样,您的参数解析器最终将始终在video 中接收一个整数(您传递一个整数或convertvalues 将视频文件名转换为一个整数)。要再次获取实际文件名,您可以执行类似

的操作
args = parser.parse_args()
video_file = VideoFiles[VideoFilesIndicator.index(args.video)]
return VideoReading(video_file)

我的建议是尝试对代码进行最少的更改。但是,如果您对代码的最终形状不满意,您也可以考虑对程序进行更多更改,like flevinkelming suggests。

【讨论】:

感谢您的回答。我试过了,但现在出现以下错误:'cv2.error: D:\Build\OpenCV\opencv-3.2.0\modules\highgui\src\window.cpp:312: error: (-215) size.width >0 && size.height>0 在函数 cv::imshow' 中。当“cv2”(图像读取包)没有得到要处理的帧时,会出现此错误。所以基本上它没有得到视频文件名。我需要传递视频文件名,而不是字典的值。 @jdhesa:我试过你的答案,但我收到 VideoFiles 错误。不过谢谢你的回答。【参考方案2】:

你的字典倒退了;您想将数字映射到文件名,以便在输入数字时可以返回文件名。无需提供来自 convertvalues 的默认值,因为您使用 choices 将允许的输入限制为 dict 的有效键。

def main():

    video_files = ["Video1.mp4", "Video2.mp4"]

    model_list = dict(enumerate(video_files, start=1))

    print(model_list)


    parser = argparse.ArgumentParser()
    group = parser.add_mutually_exclusive_group()

    group.add_argument("-v", "--video", 
                       help="add video file name of any format",
                       type=lambda str: model_list[int(str)],
                       choices=model_list.values())

    args = parser.parse_args()

    return VideoReading(args.video)

【讨论】:

感谢您的回答。但现在我收到了此代码的 Typeerror:TypeError: unhashable type: 'dict'。 不确定argparse 究竟是如何产生该错误的,但我已经做了一些修复(顺便说一句?)将其删除。 感谢您的回答。但我尝试了 flevinkelming 选项,它解决了我的问题。但我建议您使用 enumerate 创建字典对我非常有用。 我喜欢 flevinkelming 在参数解析之后而不是在解析期间将数字转换为文件名的方法。【参考方案3】:

另一种解决方案,代码最少,为用户提供动态help 输出:

import argparse

def main():

    model = 
        1: "Video1.mp4",
        2: "Video2.mp4",
        3: "Video3.mp4"
      # Add more if needed

    videos = ['()'.format(v, str(k)) for k, v in model.items()]
    help_ = "Videos to choose from: ".format(', '.join(videos))

    parser = argparse.ArgumentParser()
    parser.add_argument('-v', '--video', help=help_, type=int, default=1)
    args = parser.parse_args()

    return VideoReading(model[args.video])

if __name__ == '__main__':
    main()

python VideoReading.py -h:

usage: VideoReading.py [-h] [-v VIDEO]

optional arguments:
    -h, --help  show this help message and exit
    -v VIDEO, --v VIDEO
                      Videos to choose from: Video1.mp4(1), Video2.mp4(2),
                      Video3.mp4(3)

python VideoReading.py:

如果您正在打印选择 - Video1.mp4

python VideoReading.py -v 3:

如果您正在打印选择 - Video3.mp4

【讨论】:

感谢您的回答。它不仅解决了我的问题,而且你已经很好地解释了它。再次感谢! 很高兴能帮上忙!

以上是关于使用 Argparse 进行字典的主要内容,如果未能解决你的问题,请参考以下文章

使用其他命名空间/字典更新 argparse 命名空间

Python将字典转换为argparse

使用 argparse 和 python 接受字典作为参数 [重复]

将 Python argparse.Namespace() 视为字典的正确方法是啥?

Python argparse 字典 arg

通过 argparse 传递 JSON 字典和一个 char