3

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

如果我在代码中定义了一组“强制”选项,然后在调用程序时添加了一个附加选项,我会得到一个由parse_command_line().

获取例如带有剩余(未定义)选项的字典将非常方便。也就是说,与**kwargs函数中的工作方式大致相同。

这可以做到吗?

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


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

4

2 回答 2

4

You can create subclass of OptionParser singleton and modify parsing method. Example:

#!/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()

The only difference from source is I'm defining passed option instead of throwing an Exception. Running:

python test.py --myoption="test"
于 2013-10-29T15:56:31.827 回答
3

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

也可以使用 argparse 或其他命令行库来代替tornado.options.parse_command_line- 龙卷风的其余部分并不关心您是否正在使用tornado.options

于 2013-10-31T20:32:00.637 回答