call_command参数是必需的 [英] call_command argument is required

查看:334
本文介绍了call_command参数是必需的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图以非常类似于 call_command -command-fail-with-missing-required-arguments>这个问题没有答案



我所说的方式是: p>

  args = [] 
kwargs = {
'solr_url':'http://127.0.0.1: 8983 / solr / collection1',
'type':'comments',
'update':True,
'everything':True,
'do_commit' b $ b'traceback':True,
}
call_command('cl_update_index',** kwargs)

根据文档。但是它不起作用,只是不行。



这是我的Command类的 add_arguments 方法:

  def add_arguments(self,parser):
parser.add_argument(
'--type'
type = valid_obj_type,
required = True,
help ='由于Solr索引松散绑定到数据库,'
'命令要求在此提供正确的模型'
'参数当前选项是音频或意见。

parser.add_argument(
'--solr-url',
required = True,
type = str,
help ='当交换核心时,使用临时'
'Solr URL可能是有价值的,覆盖默认值'
'设置,例如http://127.0.0.1:8983/solr/swap_core'


actions_group = parser.add_mutually_exclusive_gro up()
actions_group.add_argument(
'--update',
action ='store_true',
default = False,
help ='运行命令更新模式。使用它来添加或更新'
'项目'

actions_group.add_argument(
'--delete',
action ='store_true',
default = False,
help ='以删除模式运行命令,使用此功能从索引中删除项目'
'。请注意,这不会从'
'中删除项目数据库中不存在的索引'

parser.add_argument(
'--optimize',
action ='store_true',
default = False,
help ='在$ $ $ $ $ $ $ $

parser.add_argument(
)之后,对当前索引执行优化命令'--do-commit',
action ='store_true',
default = False,
help ='执行一个简单的提交,没有更多的'


act_upon_group = parser.add_mutua lly_exclusive_group()
act_upon_group.add_argument(
'--everything',
action ='store_true',
default = False,
help ='对所有内容采取行动在

act_upon_group.add_argument(
'--query',
help ='对满足查询的项目采取行动。查询应该是'
'格式化为Python定义如:{\'court_id\':\'haw\'}'

act_upon_group.add_argument(
'--items',
type = int,
nargs ='*',
help ='使用单个'
'对项目列表执行操作芹菜任务'

act_upon_group.add_argument(
'--datetime',
type = valid_date_time,
help ='对比日期更新的项目采取行动YYYY-MM-DD)或'
'日期和时间(YYYY-MM-DD HH:MM:SS)'

无论我在这里做什么,我得到:


CommandError:Error:参数 - 类型是必需的


任何想法?如果您真的很好奇,可以请看这里的整个代码

解决方案

您使用定义了一个参数 - 键入'需要。该命令行将需要一个字符串或字符串,看起来像 - 类型avalue



这看起来像相关一部分 call_command

  def call_command(name,* args,* *选项)
....
parser = command.create_parser('',name)
如果command.use_argparse:
#使用`dest`选项名称解析器选项
opt_mapping = {sorted(s_opt.option_strings)[0] .lstrip(' - ')。replace(' - ','_'):s_opt.dest
for s_opt in parser._actions如果s_opt.option_strings}
arg_options = {opt_mapping.get(key,key):key的值,options.items()中的值
defaults = parser.parse_args(args = args)
defaults = dict(defaults._get_kwargs(),** arg_options)
#将位置参数从选项中移出,以模仿旧版optparse
args = defaults.pop('args',())

它创建一个参数ser,使用它自己的参数加上你添加的参数。



parser._actions如果s_opt.option_strings 是参数(操作),它采用选项标志(以 - 或 - 开头)。 opt_mapping 是标志字符串(减去前导-s)和'dest'属性之间的映射。



code> arg_options 将您的 ** kwargs 转换为可以与解析器输出。



defaults = parser.parse_args(args = args)进行实际的解析。也就是说,它是实际使用 argparse 解析机制的唯一代码。因此,您的呼叫的 * args 模拟从交互式呼叫中生成 sys.argv [1:] 。 p>

根据这个阅读我认为这应该工作:

  args = [ 
'--solr-url','http://127.0.0.1:8983/solr/collection1',
'--type','comments',
' - 更新'
'--everything',
'--do_commit',
'--traceback',
}
call_command('cl_update_index',* args)

而不是 ** kwargs 我正在传递值作为字符串列表。或者两个必需的参数可以在 args 中传递,其余的 ** kwargs

  args = ['--solr-url','http://127.0.0.1:8983/solr/ collection1',
'--type','comments']
kwargs = {
'update':True,
'everything':True,
'do_commit ':True,
'traceback':True,
}
call_command('cl_update_index',* args,** kwargs)

如果参数是需要,则需要通过 * args ** kwargs 绕过解析器,导致它反对丢失参数。






我已下载最新的 django ,但尚未安装。但是,这是一个 call_command 的模拟,应该测试调用选项:

  import argparse 

def call_command(name,* args,** options):

使用给定的选项和args / kwargs调用给定的命令
独立模拟django.core.mangement call_command

command = name

....

#模拟参数解析以获取默认选项(有关详细信息,请参阅#10080)。
parser = command.create_parser('',name)
如果command.use_argparse:
#使用解析器选项中的`dest`选项名称
opt_mapping = {sorted(s_opt如果s_opt.option_strings}
arg_options = {...},则返回值为' opt_mapping.get(key,key):value的值,在options.items()中的值)
defaults = parser.parse_args(args = args)
defaults = dict(defaults._get_kwargs(),* * arg_options)
#将位置参数从选项中移出以模拟遗留的optparse
args = defaults.pop('args',())
else:
#遗留的optparse方法
defaults,_ = parser.parse_args(args = [])
defaults = dict(defaults .__ dict__,** options)
如果'skip_checks'不在选项中:
defaults [ 'skip_checks'] = True

return command.execute(* args,** de错误)

class BaseCommand():
def __init __(self):
self.use_argparse = True
self.stdout = sys.stdout
self .stderr = sys.stderr
def execute(self,* args,** kwargs):
self.handle(* args,** kwargs)
def handle(self,* args, ** kwargs)
print('args:',args)
print('kwargs:',kwargs)
def create_parser(self,* args,** kwargs):
parser = argparse.ArgumentParser()
self.add_arguments(parser)
return parser
def add_arguments(self,parser):
parser.add_argument(' - type' ,required = True)
parser.add_argument(' - update',action ='store_true')
parser.add_argument(' - 可选',默认='默认')
解析器.add_argument('foo')
parser.add_argument('args',nargs ='*')

如果__name __ =='__ main__':

testcmd = BaseCommand()
#testcmd.execute('one','tow',three ='four')

call_command(testcmd,'--type','typevalue','foovalue','argsvalue',update = true)

args = ['--type = argvalue','foovalue','1','2']
kwargs = {
'solr_url' http://127.0.0.1 ...',
'type':'comments',
'update':True,
'everything':True,
}
call_command(testcmd,* args,** kwargs)

产生:

  python3 stack32036562.py 
args:('argsvalue',)
kwargs:{'optional':'default' ,'type':'typevalue','update':True,'skip_checks':True,'foo':'foovalue'}
args:('1','2')
kwargs: {'optional':'default','update':True,'foo':'foovalue','type':'comments','skip_checks':True,'everything':True,'solr_url' ttp://127.0.0.1 ...'}

使用一堆存根,我可以您的 cl 命令使用我的 BaseCommand ,以及以下通话作品:

  clupdate = Command()
args = ['--type',' - solr-url','dummy']
kwargs = {
'solr_url':'http://127.0.0.1:8983/solr/collection1',
#'type' :'comments',
'update':True,
'everything':True,
'do_commit':True,
'traceback':True,
}
call_command(clupdate,* args,** kwargs)

执行一个存根一切

 以更新模式运行... 
一切
args:()
options:{'type':'opinion','query':None,'solr_url':'http://127.0.0.1:8983/solr/collection1','items' :无,'do_commit':True,'update':True,'delete':False,'dat etime':None,'optimize':False,'skip_checks':True,'everything':True,'traceback':True}


I'm trying to use Django's call_command in a manner very similar to this question without an answer.

The way I'm calling it is:

    args = []
    kwargs = {
        'solr_url': 'http://127.0.0.1:8983/solr/collection1',
        'type': 'opinions',
        'update': True,
        'everything': True,
        'do_commit': True,
        'traceback': True,
    }
    call_command('cl_update_index', **kwargs)

In theory, that should work, according to the docs. But it doesn't work, it just doesn't.

Here's the add_arguments method for my Command class:

def add_arguments(self, parser):
    parser.add_argument(
        '--type',
        type=valid_obj_type,
        required=True,
        help='Because the Solr indexes are loosely bound to the database, '
             'commands require that the correct model is provided in this '
             'argument. Current choices are "audio" or "opinions".'
    )
    parser.add_argument(
        '--solr-url',
        required=True,
        type=str,
        help='When swapping cores, it can be valuable to use a temporary '
             'Solr URL, overriding the default value that\'s in the '
             'settings, e.g., http://127.0.0.1:8983/solr/swap_core'
    )

    actions_group = parser.add_mutually_exclusive_group()
    actions_group.add_argument(
        '--update',
        action='store_true',
        default=False,
        help='Run the command in update mode. Use this to add or update '
             'items.'
    )
    actions_group.add_argument(
        '--delete',
        action='store_true',
        default=False,
        help='Run the command in delete mode. Use this to remove  items '
             'from the index. Note that this will not delete items from '
             'the index that do not continue to exist in the database.'
    )
    parser.add_argument(
        '--optimize',
        action='store_true',
        default=False,
        help='Run the optimize command against the current index after '
             'any updates or deletions are completed.'
    )
    parser.add_argument(
        '--do-commit',
        action='store_true',
        default=False,
        help='Performs a simple commit and nothing more.'
    )

    act_upon_group = parser.add_mutually_exclusive_group()
    act_upon_group.add_argument(
        '--everything',
        action='store_true',
        default=False,
        help='Take action on everything in the database',
    )
    act_upon_group.add_argument(
        '--query',
        help='Take action on items fulfilling a query. Queries should be '
             'formatted as Python dicts such as: "{\'court_id\':\'haw\'}"'
    )
    act_upon_group.add_argument(
        '--items',
        type=int,
        nargs='*',
        help='Take action on a list of items using a single '
             'Celery task'
    )
    act_upon_group.add_argument(
        '--datetime',
        type=valid_date_time,
        help='Take action on items newer than a date (YYYY-MM-DD) or a '
             'date and time (YYYY-MM-DD HH:MM:SS)'
    )

No matter what I do here, I get:

CommandError: Error: argument --type is required

Any ideas? If you're truly curious, you can see the entire code here.

解决方案

You defined an argument with a '--type' flag, and made it required. That command line will require a string or strings that look like --type avalue.

This looks like the relevant part of call_command:

def call_command(name, *args, **options):
    ....
    parser = command.create_parser('', name)
    if command.use_argparse:
        # Use the `dest` option name from the parser option
        opt_mapping = {sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest
                       for s_opt in parser._actions if s_opt.option_strings}
        arg_options = {opt_mapping.get(key, key): value for key, value in options.items()}
        defaults = parser.parse_args(args=args)
        defaults = dict(defaults._get_kwargs(), **arg_options)
        # Move positional args out of options to mimic legacy optparse
        args = defaults.pop('args', ())

It creates a parser, using it's own arguments plus the ones you add.

parser._actions if s_opt.option_strings are the arguments (Actions) that take an option flag (start with - or --). opt_mapping is map between the flag strings (minus the leading -s) and the 'dest' attribute.

arg_options converts your **kwargs to something that can be merged with the parser output.

defaults = parser.parse_args(args=args) does the actual parsing. That is, it's the only code that actually uses the argparse parsing mechanism. So the *args part of your call simulates generating sys.argv[1:] from an interactive call.

Based on that reading I think this should work:

args = [
    '--solr-url', 'http://127.0.0.1:8983/solr/collection1',
    '--type', 'opinions',
    '--update'
    '--everything',
    '--do_commit',
    '--traceback',
}
call_command('cl_update_index', *args)

Instead of **kwargs I am passing in values as a list of strings. Or the two required arguments could be passed in args, and the rest in **kwargs.

args = ['--solr-url', 'http://127.0.0.1:8983/solr/collection1',
    '--type', 'opinions']
kwargs = {
    'update': True,
    'everything': True,
    'do_commit': True,
    'traceback': True,
}
call_command('cl_update_index', *args, **kwargs)

If an argument is required it needs to passed in through *args. **kwargs bypass the parser, causing it to object about missing arguments.


I've downloaded the latest django, but haven't installed it. But here's a simulation of call_command that should test the calling options:

import argparse

def call_command(name, *args, **options):
    """
    Calls the given command, with the given options and args/kwargs.
    standalone simulation of django.core.mangement call_command
    """
    command = name
    """
    ....
    """
    # Simulate argument parsing to get the option defaults (see #10080 for details).
    parser = command.create_parser('', name)
    if command.use_argparse:
        # Use the `dest` option name from the parser option
        opt_mapping = {sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest
                       for s_opt in parser._actions if s_opt.option_strings}
        arg_options = {opt_mapping.get(key, key): value for key, value in options.items()}
        defaults = parser.parse_args(args=args)
        defaults = dict(defaults._get_kwargs(), **arg_options)
        # Move positional args out of options to mimic legacy optparse
        args = defaults.pop('args', ())
    else:
        # Legacy optparse method
        defaults, _ = parser.parse_args(args=[])
        defaults = dict(defaults.__dict__, **options)
    if 'skip_checks' not in options:
        defaults['skip_checks'] = True

    return command.execute(*args, **defaults)

class BaseCommand():
    def __init__(self):
        self.use_argparse = True
        self.stdout= sys.stdout
        self.stderr=sys.stderr
    def execute(self, *args, **kwargs):
        self.handle(*args, **kwargs)
    def handle(self, *args, **kwargs):
        print('args: ', args)
        print('kwargs: ', kwargs)
    def create_parser(self, *args, **kwargs):
        parser = argparse.ArgumentParser()
        self.add_arguments(parser)
        return parser
    def add_arguments(self, parser):
        parser.add_argument('--type', required=True)
        parser.add_argument('--update', action='store_true')
        parser.add_argument('--optional', default='default')
        parser.add_argument('foo')
        parser.add_argument('args', nargs='*')

if __name__=='__main__':

    testcmd = BaseCommand()
    # testcmd.execute('one','tow', three='four')

    call_command(testcmd, '--type','typevalue','foovalue', 'argsvalue', update=True)

    args = ['--type=argvalue', 'foovalue', '1', '2']
    kwargs = {
        'solr_url': 'http://127.0.0.1...',
        'type': 'opinions',
        'update': True,
        'everything': True,
    }
    call_command(testcmd, *args, **kwargs)

which produces:

python3 stack32036562.py 
args:  ('argsvalue',)
kwargs:  {'optional': 'default', 'type': 'typevalue', 'update': True, 'skip_checks': True, 'foo': 'foovalue'}
args:  ('1', '2')
kwargs:  {'optional': 'default', 'update': True, 'foo': 'foovalue', 'type': 'opinions', 'skip_checks': True, 'everything': True, 'solr_url': 'http://127.0.0.1...'}

With a bunch of stubs, I can make your cl Command work with my BaseCommand, and the following call works:

clupdate = Command()
args = ['--type','opinions','--solr-url','dummy']
kwargs = {
    'solr_url': 'http://127.0.0.1:8983/solr/collection1',
    #'type': 'opinions',
    'update': True,
    'everything': True,
    'do_commit': True,
    'traceback': True,
}
call_command(clupdate, *args, **kwargs)

performing a stub everything.

Running in update mode...
everything
args:  ()
options:  {'type': 'opinions', 'query': None, 'solr_url': 'http://127.0.0.1:8983/solr/collection1', 'items': None, 'do_commit': True, 'update': True, 'delete': False, 'datetime': None, 'optimize': False, 'skip_checks': True, 'everything': True, 'traceback': True}

这篇关于call_command参数是必需的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆