Python 使用Tornado选项处理任意选项,例如**kwargs

Python 使用Tornado选项处理任意选项,例如**kwargs,python,python-2.7,tornado,keyword-argument,Python,Python 2.7,Tornado,Keyword Argument,我正在使用Tornado选项定义命令行参数。但是,我希望能够将代码中未定义的任意配置选项抛出到我的程序中。根据程序应该做什么,这些将有所不同。例如,使用MAC地址连接到蓝牙设备,或使用TTY连接到串行设备 如果我在代码中定义了一组“强制”选项,然后在调用程序时添加了一个额外的选项,那么parse_command_line()会引发异常 这将是非常方便的,例如,获得一个字典与剩余的(未定义的)选项。也就是说,**kwargs在函数中的工作方式与此非常相似 这能做到吗 (解决方法是定义一个名为(例如

我正在使用
Tornado选项
定义命令行参数。但是,我希望能够将代码中未定义的任意配置选项抛出到我的程序中。根据程序应该做什么,这些将有所不同。例如,使用MAC地址连接到蓝牙设备,或使用TTY连接到串行设备

如果我在代码中定义了一组“强制”选项,然后在调用程序时添加了一个额外的选项,那么
parse_command_line()
会引发异常

这将是非常方便的,例如,获得一个字典与剩余的(未定义的)选项。也就是说,
**kwargs
在函数中的工作方式与此非常相似

这能做到吗

(解决方法是定义一个名为(例如)配置的字符串选项,并将所有内容都放在其中,可能以某种巧妙的方式进行编码。当另一个程序调用该程序时,我可以(例如)对序列化的dict进行base64编码。)



更新:我注意到,如果您添加的命令行参数没有前导破折号,Tornado将忽略它们并返回一个包含剩余(未定义)选项的列表。

您可以创建
OptionParser
singleton的子类并修改解析方法。例如:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import OptionParser
import sys

class MyOptionParser(OptionParser):
    def parse_command_line(self, args=None, final=True):
        if args is None:
            args = sys.argv
        remaining = []
        for i in range(1, len(args)):
            # All things after the last option are command line arguments
            if not args[i].startswith("-"):
                remaining = args[i:]
                break
            if args[i] == "--":
                remaining = args[i + 1:]
                break
            arg = args[i].lstrip("-")
            name, equals, value = arg.partition("=")
            name = name.replace('-', '_')
            if not name in self._options:
#   modified line       self.print_help()
#   modified line       raise Error('Unrecognized command line option: %r' % name)
                self.define(name, help="Arbitrary option") # new line
            option = self._options[name]
            if not equals:
                if option.type == bool:
                    value = "true"
                else:
                    raise Error('Option %r requires a value' % name)
            option.parse(value)

        if final:
            self.run_parse_callbacks()

        return remaining

options = MyOptionParser()
options.define("port", default=8000, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        self.write(options.myoption) 

if __name__ == "__main__":
    options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()
唯一的区别是我定义了passed选项,而不是抛出异常。运行:

python test.py --myoption="test"

tornado.options的理念是,任何模块都可以定义选项,而不仅仅是主要入口点。因此,如果您可能需要蓝牙mac地址,您应该在与蓝牙交互的模块中定义该选项。(如果您可能需要多个,则可以设置multiple=True)。唯一棘手的部分是,在调用parse_命令行之前,必须导入定义选项的所有模块。tornado.options不支持真正的任意选项


也可以使用argparse或其他命令行库来代替tornado.options.parse\u命令行-tornado的其余部分并不关心您是否使用tornado.options。

您尝试过使用argparse吗?听起来很混乱。为什么不使用一个强制参数来确定可行的选项,并可以分派到某个对象以适当地处理它们呢。否则,听起来像是你在为人们开放,让他们混合不同/可能冲突的选项…@Jon Clements:设置可行选项的强制参数是一个非常好的主意。只要在调用parse_command_line()时定义了所有选项,它就可以工作。此外,我认为当一个必需的参数未填充时,它甚至会反映在提供的帮助消息上。@GamesBrainiac:是的,但不在这个项目中。龙卷风是这里的必要条件。