7

我编写这个简短的小程序是为了自学 Python 中的面向对象设计。但是我目前遇到了一个非常令人困惑的错误。

  Traceback (most recent call last):
  File "main.py", line 97, in <module>
  cli()
  File "C:\Python27\lib\site-packages\click\core.py", line 716, in __call__
  return self.main(*args, **kwargs)
  File "C:\Python27\lib\site-packages\click\core.py", line 695, in main
  with self.make_context(prog_name, args, **extra) as ctx:
  File "C:\Python27\lib\site-packages\click\core.py", line 620, in make_context
  self.parse_args(ctx, args)
  File "C:\Python27\lib\site-packages\click\core.py", line 874, in parse_args
  value, args = param.handle_parse_result(ctx, opts, args)
  File "C:\Python27\lib\site-packages\click\core.py", line 1390, in handle_parse_result
  value = self.full_process_value(ctx, value)
  File "C:\Python27\lib\site-packages\click\core.py", line 1675, in full_process_value
  return Parameter.full_process_value(self, ctx, value)
  File "C:\Python27\lib\site-packages\click\core.py", line 1359, in full_process_value
  value = self.process_value(ctx, value)
  File "C:\Python27\lib\site-packages\click\core.py", line 1349, in process_value
  return self.type_cast_value(ctx, value)
  File "C:\Python27\lib\site-packages\click\core.py", line 1332, in type_cast_value
  return self.type(value or (), self, ctx)
  File "C:\Python27\lib\site-packages\click\types.py", line 38, in __call__
  return self.convert(value, param, ctx)
  File "C:\Python27\lib\site-packages\click\types.py", line 472, in convert
  raise TypeError('It would appear that nargs is set to conflict '
  TypeError: It would appear that nargs is set to conflict with the composite type arity.

这个错误是由我的基于点击的 CLI 引发的。这很奇怪,因为引发错误的选项之一没有任何参数。

#-*- coding: utf-8 -*-

import click
import json
import glob
import os

def prompt(question):
    val = raw_input(question + ' > ')
    return val

def mkdir(path):
    if not os.path.isdir(str(path)):
            os.mkdir(str(path))
    return str(path)


class Profile(object):
    def __init__(self, name, age, weight, job, salary):
        self.name = name
        self.age = age
        self.weight = weight
        self.job = job
        self.salary = salary

        self.data = { 'name' : '',
                      'age' : '',
                      'weight' : '',
                      'job': '',
                      'salary' : ''
                     }

    def new_profile(self, name, age, job, weight, salary, fname):
        self.data['name'] = name
        self.data['age'] = age
        self.data['job'] = job
        self.data['weight'] = weight
        self.data['salary'] = salary
        self.fname = fname

        self.dirname = mkdir('.profiles\\')

        with open(str(self.dirname) + str(self.fname) + '.json', 'w') as self.profile:
            json.dump(self.data, self.profile)

        print 'Profile saved!'


    def list_profile(self):
        print glob.glob('.profiles/*.json')

    def print_profile(self, fname):
        try:
            self.fname = fname

            with open('.profiles\\' + str(self.fname) + '.json') as data_file:
                self.profile = json.load(data_file)

            self.name = self.profile['name']
            self.age = self.profile['age']
            self.weight = self.profile['weight']
            self.job = self.profile['job']
            self.salary = self.profile['salary']

            print 'name: {}\nage: {}\nweight: {}\noccupation: {}\nsalary: {}'.format(self.name, self.age, self.weight, self.job, self.salary)

        except IOError:
            print 'File not found'

@click.command(options_metavar='<options>')
@click.option('--new_profile', '-n',
              nargs=6,
              type=click.Tuple([str, str, str, str, str, str]),
              metavar='<name, age, occupation, weight, salary, filename>',
              help='Creates a new profile')
@click.option('--list_profile', '-l',
              is_flag=True,
              help='Lists all profiles that currently exist')
@click.option('--print_profile', '-p',
              type=(str),
              metavar='<profile name>',
              help = 'prints data from a saved profile')
def cli(new_profile, list_profile, print_profile):
    profile = Profile('', '', '', '', '')

    if new_profile:
        profile.new_profile(new_profile[0], new_profile[1], new_profile[2], new_profile[3], new_profile[4], new_profile[5]) # name, age, job, weight, salary, fname
    elif list_profile:
        profile.list_profile()
    elif print_profile:
        profile.print_profile(print_profile)

if __name__ == '__main__':
    cli()

我一直在努力解决这个回溯大约一天,但没有任何结果。有什么建议么?谢谢!

编辑:我修复了它,但我在这个过程中创建了一个逻辑错误。

default=(None, None, None, None, None, None))

我将此参数添加到单击选项 new_profile 中。但是当您使用任何其他参数时,它只会运行

Profile.new_profile(None, None None, None, None None)

从而创建一个新文件none.json.profile所有值都为空。所以我想我在技术上解决了这个问题,但我创造了一个更大的问题。

4

1 回答 1

6

有几种方法可以解决此问题。

不使用click.Tuple

Tuple适用于非统一类型的多值参数。由于您使用的是 6 个字符串,因此可以通过以下方式更简单地完成此操作:

@click.option('--new_profile', '-n',
              nargs=6,
              type=str,
              ....

click.Tuple与默认值一起使用

正如您所发现的,click.Tuple如果您指定默认值,则可以使用 a 。

@click.option('--new_profile', '-n',
              default=[None] * 6,
              type=click.Tuple([str, str, str, str, str, str]),
              ....

然后,您可以确定您没有获得默认值,例如:

if new_profile and None not in new_profile:
    # create a new profile
    ....
于 2017-05-26T14:52:00.027 回答