Argparse + cmd2 RecursionError即使在简单程序上

问题描述

示例代码

package com.missingVariable.Application;

import java.util.Random;
import java.util.concurrent.TimeUnit;

class Bot { // I created a class 
    public final int originalSN = 0; // Original serial number to be searched

    private final int rangeSerialNumber = 1000;

    private Random SN = new Random(); // Serial number randomizer
    
    // Bot serial number
    private int botSerialNumber = SN.nextInt(rangeSerialNumber); // Sets the bot's serial number

    public int getSN() { // A getter for the bot's serial number
        return this.botSerialNumber;
    }

    // Bot parent number
    private int parentSerialNumber = SN.nextInt(rangeSerialNumber); // Sets the bot's parent number

    public int getParentSN() { // A getter for the bot's serial number
        return this.parentSerialNumber;
    }

    public void setNewBotSN(int botSerialNumber) {
        this.botSerialNumber = botSerialNumber;
    }
    
    // Bot constructor
    public Bot() {
        System.out.println("Bot serial number " + getSN());
        System.out.println("Bot parent number " + getParentSN());
        System.out.println();

    }
}

public class Application {

    public static void main(String[] args) throws InterruptedException {
        int botCounter = 0;
        int botPopulation = 1000;

        // Loop
        while (botCounter < botPopulation) {
            TimeUnit.SECONDS.sleep(1); // Delay
            Bot bot = new Bot(); // Creates new bot
            if (bot.getSN() == bot.originalSN) { // Main Code
                System.out.println("Bot found!");
                break;
            } else {
                System.out.println("Current bot serial number does not match");
                bot.setNewBotSN(bot.getParentSN()); // Changes the the serial number to parent number
                System.out.println("New bot serial number is " + bot.getSN());
                System.out.println();
                botCounter++;
            }
        }
    }
}

在示例中,我试图制作一个可以在单一模式(import argparse import cmd2 import sys def create_subparser(a_parser = None): if a_parser is None: new_parser = argparse.ArgumentParser() else: new_parser = a_parser.add_parser("single") new_parser.add_argument("--single-param","-sp") return new_parser def single_print(some_param): print("single operation " + str(some_param)) def other_print(): print("other operation") class TestCmd(cmd2.Cmd): single_parser = create_subparser() @cmd2.with_argparser(single_parser) def do_single(self,opts): print(opts) single_print(opts.single_param) def do_other(self,opts): other_print() if __name__ == "__main__": parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(help="commands",dest="mode") create_subparser(subparsers) cmd_parser = subparsers.add_parser("cmd",help="shell") args = parser.parse_args() if args.mode == "single": single_print(args.single_param) else: sys.argv = [sys.argv[0]] # cmd2 complains about unkNown parameters without cmd = TestCmd() cmd.cmdloop() )或cmd /提示模式(program.py single -sp test)下运行的程序,然后将其称为单一模式或其他操作(在外壳内部,编写program.py cmdsingle -sp test。无论如何,如果我尝试获取cmd2类中do_single中使用的argparse的所有值,我将得到other使用cmd2的调试,它可以完成:

EXCEPTION of type 'RecursionError' occurred with message: 'maximum recursion depth exceeded in comparison'

我使用Traceback (most recent call last): File "/home/.../site-packages/cmd2/cmd2.py",line 2011,in onecmd_plus_hooks stop = self.onecmd(statement,add_to_history=add_to_history) File "/home/.../site-packages/cmd2/cmd2.py",line 2441,in onecmd stop = func(statement) File "/home/.../site-packages/cmd2/decorators.py",line 308,in cmd_wrapper return func(*args_list,**kwargs) File "test.py",line 28,in do_single print(opts) File "/usr/lib/python3.7/argparse.py",line 131,in __repr__ arg_strings.append('%s=%r' % (name,value)) File "/usr/lib/python3.7/argparse.py",value)) [PrevIoUs line repeated 326 more times] File "/usr/lib/python3.7/argparse.py",line 129,in __repr__ for name,value in self._get_kwargs(): File "/usr/lib/python3.7/argparse.py",line 139,in _get_kwargs return sorted(self.__dict__.items()) RecursionError: maximum recursion depth exceeded in comparison 函数的原因是因为我正在创建要由cmd2.Cmd子类使用的子解析器,但是当从主调用时,我想对模式使用相同的解析器贝壳。这基本上是一个最低限度的工作示例,我的代码有很多标志和其他内容

另一方面,该问题似乎是由于create_subparser而引起的。似乎它尝试执行print(opts),并且在尝试枚举所有变量时,由于某处的递归而耗尽了内存。如果我不尝试列出对象内的所有变量(例如,如果我仅使用vars(opts)),它将起作用。这似乎与我试图在cmd2内部和主程序中使用相同的argparser有关,但是我不明白为什么它确实在发生以及它是否可以解决

解决方法

没有cmd2,我无法运行您的代码。但是我可以创建一个可以解决您问题的名称空间。

In [429]: ns = argparse.Namespace(foo='bar',baz=12)                                                 
In [430]: ns.ns = ns                                                                                 
In [431]: print(ns)                                                                                  
---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-431-0769451eb86e> in <module>
----> 1 print(ns)

/usr/lib/python3.6/argparse.py in __repr__(self)
    133         for name,value in self._get_kwargs():
    134             if name.isidentifier():
--> 135                 arg_strings.append('%s=%r' % (name,value))
    136             else:
    137                 star_args[name] = value

... last 1 frames repeated,from the frame below ...

/usr/lib/python3.6/argparse.py in __repr__(self)
    133         for name,value))
    136             else:
    137                 star_args[name] = value

RecursionError: maximum recursion depth exceeded while calling a Python object

您可以测试各个属性,直到找到问题所在:

In [432]: list(ns.__dict__.keys())                                                                   
Out[432]: ['foo','baz','ns']