导入的 python 模块覆盖选项解析器

Posted

技术标签:

【中文标题】导入的 python 模块覆盖选项解析器【英文标题】:Imported python module overrides option parser 【发布时间】:2016-04-05 15:18:45 【问题描述】:

我编写了一个 python 实用程序脚本,它使用 optparse 在脚本启动时包含选项和标志。

一切都很好,但是当我导入 google API oauth2client 并运行它的执行函数时,它会将我的 add_options 覆盖到它使用的选项中。

当我说“覆盖”时,我的意思是即使我的脚本将选项添加到我的选项解析器,当我像这样执行脚本时:

./myscript --help

我收到了我添加到脚本中的选项的详细回复:

Usage: myscript [options]

Options:
    -h, --help            show this help message and exit
    -u USER, --user=USER  resources owned by this username

但是,当我像这样实际执行我的脚本时:

./myscript --user myuser

我收到以下错误:

usage: smyscript [-h] [--auth_host_name AUTH_HOST_NAME]
               [--noauth_local_webserver]
               [--auth_host_port [AUTH_HOST_PORT     
               [AUTH_HOST_PORT  ...]]]
               [--logging_level 
               DEBUG,INFO,WARNING,ERROR,CRITICAL]
 myscript: error: unrecognized arguments: --user myuser

要知道的另一件重要事情是,我正在使用自己的模块来包装 oauth2client,如下所示:

import oauth2client
import argparse

def execute():

    parser = argparse.ArgumentParser(
            description=__doc__,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            parents=[tools.argparser])
            # don't use any flags                                                                           
    flags = parser.parse_args(None)

    flow = client.flow_from_clientsecrets(
             client_secret_path,
             scope=scope_path,
             message=tools.message_if_missing(client_secret))
    # open credential storage path                                                                                                                                                                 
     credential_storage =  file.Storage(self._credential_storage_path)
     credentials = credential_storage.get()
     # get credentails if necessary                                                                                                                                                                 
     if credentials is None or credentials.invalid:
          credentials = tools.run_flow(flow, credential_storage, flags)                                                                                       

然后我的脚本看起来像这样:

import myown_oauth2client_wrapper

from optparse import OptionParser

if __name__ == "__main__":
    usage = "something"
    parser_ = OptionParser(usage)

    parser_.add_option("-u","--user")
    (options_, args) = parser_.parse_args()

    myown_oauth2client_wrapper.execute()

如何避免此选项覆盖?

沙哈

【问题讨论】:

更具体地说明您遇到的错误。我怀疑它是否会改变你的parser_。它更有可能实现自己的解析器(基于argparse),并解析相同的sys.argv。错误消息将提供线索。还有其他argparse问题涉及googleapi 告诉我们您正在导入哪个模块,您正在调用什么函数以及为什么您认为add_option 已被覆盖? 没有足够的信息来回答这个问题,而且由于海报甚至不会告诉我们正在调用哪个函数,所以需要关闭它。 嘿@tdelaney,感谢您的回复。我已经编辑了我的问题以添加缺失的细节。希望现在好多了 【参考方案1】:

在上一个问题中,Getting Youtube data using Python

我发现google api使用argparse

from outh2client.tools import argparser

我的推断是它在导入时解析sys.argv

正如我在评论中所问的,我们需要知道您遇到了什么错误。 “覆盖”是什么意思?这说明什么?您是否收到由argparseoptparse 生成的解析器错误消息?如果有,是什么信息。

向我们展示给出错误的命令行以及错误消息。

您可能希望使用-h 调用脚本以查看谁/什么打印解析帮助消息。


所以tools.argparser 是一个argparse 解析器,其中定义了authlogging 参数。在我之前回答的问题中,用户直接使用了该解析器(添加了他们自己的)。您将该解析器用作parent

parser = argparse.ArgumentParser(...
        parents=[tools.argparser])                                                                    
flags = parser.parse_args(None)

它现在解析sys.argv。由于没有为此解析器定义 --user,因此它引发了 myscript: error: unrecognized arguments: --user myuser

一种解决方案是使用:

flags, extras = parser.parse_known_args(None)

现在我希望它能够运行,并且 extras 等于 ['--user', 'myuser']

另一种选择是为此parser 定义--user 参数。

parser.add_argument('-u','--user',help='dummy user argument')

【讨论】:

【参考方案2】:

我遇到了同样的问题。出现问题是因为 google 授权模块也使用了 argparse。您应该实现的不是共享该内存空间。我通过 argparse 接收参数,将它们加载到另一个对象中解决了这个问题,但是在调用谷歌模块之前,我做了以下事情:

import sys


sys.argv = [sys.argv[0]]

我的问题解决了。

【讨论】:

以上是关于导入的 python 模块覆盖选项解析器的主要内容,如果未能解决你的问题,请参考以下文章

parser.add_argument()用法——命令行选项参数和子命令解析器

Python Argparse 子解析器

python-argparse模块

Apollo GraphQL:增强而不是覆盖默认解析器行为

Python:正确处理子命令的全局选项的参数解析器

[Python系列-25]:argparse --- 命令行选项参数解析器