I define an argsparse object like this:
parser = argparse.ArgumentParser(description='{desc}', formatter_class=argparse.ArgumentDefaultsHelpFormatter)\
.format(desc=description)
Then I add arguments like this:
parser.add_argument("--config", "-c", help='config',
default='dbConf').format(dbConf=dbConfig)
Since I use these two lines in many scripts, I want to embed them into a function.
However, to my understanding the parser.add_argument() listens to the command line.
Is it possible to embed these lines into a function?
Is it possible to embed these lines into a function?
Yes. add_argument doesn't interact with the command line at all, though even if it did that would make little difference.
The one bit of argparse which interacts with the CLI input is the parse_args method, and what it does by default is access the global sys.argv attribute and process it. I wrote by default because you can also provide a list of strings as first parameter and it'll process that instead (if you click the link you'll see the official documentation does that to demonstrate various things in the examples).
So yes, you can very much have a function which creates an ArgumentParser and starts configuring it, then returns it for more configuration and ultimately, well, parsing the arguments.
Related
I am currently building an extension to an existing library that uses argparse.ArgumentParser() to ingest cli arguments, and have added my own argparse.ArgumentParser() using parse_known_args() to parse out the arguments I want to inject before passing the remaining arguments on to the existing library's implementation. I am doing this instead of adding the arguments to the underlying library so that if the underlying library changes, everything should still work.
However, when I pass in the --help flag my implementation of argparse.ArgumentParser() grabs that flag, prints out help for my injected arguments then breaks execution so it never gets to the help message for the underlying library.
I am having trouble figuring out if there's a way to combine the help directives for both argparse.ArgumentParser() implementations (if it's even possible), or how to ignore the help flag in my implementation. My added arguments are for debug only and are not vital to display to the end user of my extended library, so if there is a way to ignore the help flag in my implementation, that would be OK, while not ideal.
I think this may be an answer to your question. add_help=False, but added to subcommands and subparsers. Python argparse - disable help for subcommands?
You need to pass parents parameter to the subsequent parsers. I've just posted an answer to a similar question here:
Argparse: is it possible to combine help texts from multiple parsers?
I am looking for a good module that is already out there for parsing arguments on custom CLI interfaces. If you can imagine there is a CLI that gives you a prompt:
framework> commands go here....
It starts to get tedious when you add in arguments, example:
framework> command <argument1> <argument2> ...
I'd like to know if there is any sort of module that will not only make it easy to create these CLI interfaces, but one that has tab completion for each argument in a command chain. I'm tired of reinventing the wheel each time I create something like this!
framework> comma<tab>
framework> command arg<tab>
framework> command argument parame<tab>
framework> command argument parameter
You get the idea. If there is no module already out there for this sort of thing, any suggestions on an elegant solution to creating something like this in a modularized fashion, it would be much appreciated.
Please note that I do not want to parse arguments passed in through the parent process command shell (such as bash), I want to do the processing from within an infinite while loop within the script itself. For example:
while (True):
cmd = raw_input("framework> ")
framework.process_command(cmd)
Take a look at Click, "a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary": http://click.pocoo.org/5/
in python you have a build in module called argparse to manage CLI parameters application, now take a look to this module argparse extension for tab completion https://pypi.python.org/pypi/argcomplete/0.8.4
Looks like the builtin cmd module offers what you're looking for. It supports tab completion for commands and arguments. Here's a tutorial from PyMOTW. Another example here.
If you need some more customizations, there's also cmd2 which extends the builtin cmd.
In python cmd module, when I press the TAB button, I get the list of possible commands that are available and that I have defined in my cmd.Cmd class.
My question is whether it is possible to show a set of commands based on the context like in a Cisco router CLI for instance?
I don't have any experience with this lib, but doc says
If completion is enabled, completing commands will be done automatically, and completing of commands args is done by calling complete_foo() with arguments text, line, begidx, and endidx. text is the string prefix we are attempting to match: all returned matches must begin with it. line is the current input line with leading whitespace removed, begidx and endidx are the beginning and ending indexes of the prefix text, which could be used to provide different completion depending upon which position the argument is in.
So, may be you can implement context based completion in complete_foo function
I have found an answer to my question. One can use nested interpreters, so a nested interpreter is another interpreter object that will have its own commands, this way each context can be modeled by a nested interpreter. Here is a nice explanation and example:
object inheritance and nested cmd
If you want something like Cisco take a look at ishell,
ishell helps you to easily create an interactive shell for your application. It supports command completion, dynamic arguments, a command history, and chaining of commands.
https://github.com/italorossi/ishell
There's a cisco like cli example at https://github.com/italorossi/ishell/blob/master/examples/cisco.py
PS: I'm the author.
I'm developing a system that operates on (arbitrary) data from databases. The data may need some preprocessing before the system can work with it. To allow the user the specify possibly complex rules I though of giving the user the possibility to input Python code which is used to do this task. The system is pure Python.
My plan is to introduce the tables and columns as variables and let the user to anything Python can do (including access to the standard libs). Now to my problem:
How do I take a string (the user entered), compile it to Python (after adding code to provide the input data) and get the output. I think the easiest way would be to use the user-entered data a the body of a method and take the return value of that function a my new data.
Is this possible? If yes, how? It's unimportant that the user may enter malicious code since the worst thing that could happen is, that he screws up his own system, which is thankfully not my problem ;)
Python provides an exec() statement which should do what you want. You will want to pass in the variables that you want available as the second and/or third arguments to the function (globals and locals respectively) as those control the environment that the exec is run in.
For example:
env = {'somevar': 'somevalue'}
exec(code, env)
Alternatively, execfile() can be used in a similar way, if the code that you want executed is stored in its own file.
If you only have a single expression that you want to execute, you can also use eval.
Is this possible?
If it doesn't involve time travel, anti-gravity or perpetual motion the answer to this question is always "YES". You don't need to ask that.
The right way to proceed is as follows.
You build a framework with some handy libraries and packages.
You build a few sample applications that implement this requirement: "The data may need some preprocessing before the system can work with it."
You write documentation about how that application imports and uses modules from your framework.
You turn the framework, the sample applications and the documentation over to users to let them build these applications.
Don't waste time on "take a string (the user entered), compile it to Python (after adding code to provide the input data) and get the output".
The user should write applications like this.
from your_framework import the_file_loop
def their_function( one_line_as_dict ):
one_line_as_dict['field']= some stuff
the_file_loop( their_function )
That can actually be the entire program.
You'll have to write the_file_loop, which will look something like this.
def the_file_loop( some_function ):
with open('input') as source:
with open('output') as target:
for some_line in source:
the_data = make_a_dictionary( some_line )
some_function( the_data )
target.write( make_a_line( the_data ) )
By creating a framework, and allowing users to write their own programs, you'll be a lot happier with the results. Less magic.
2 choices:
You take his input and put it in a file, then you execute it.
You use exec()
If you just want to set some local values and then provide a python shell, check out the code module.
You can start an instance of a shell that is similar to the python shell, as well as initialize it with whatever local variables you want. This would assume that whatever functionality you want to use the resulting values is built into the classes you are passing in as locals.
Example:
shell = code.InteractiveConsole({'foo': myVar1, 'bar': myVar2})
What you actually want is exec, since eval is limited to taking an expression and returning a value. With exec, you can have code blocks (statements) and work on arbitrarily complex data, passed in as the globals and locals of the code.
The result is then returned by the code via some convention (like binding it to result).
well, you're describing compile()
But... I think I'd still implement this using regular python source files. Add a special location to the path, say '~/.myapp/plugins', and just __import__ everything there. Probably you'll want to provide some convenient base classes that expose the interface you're trying to offer, so that your users can inherit from them.
I have a class that handles command line arguments in my program using python's optparse module. It is also inherited by several classes to create subsets of parameters. To encapsulate the option parsing mechanism I want to reveal only a function add_option to inheriting classes. What this function does is then call optparse.make_option.
Is it a good practice to simply have my add_option method say that it accepts the same arguments as optparse.make_option in the documentation, and forward the arguments as *args and **kwargs?
Should I do some parameter checking beforehand? In a way I want to avoid this to decouple that piece of code as much from a specific version of optparse.
It seems that you want your subclasses to have awareness of the command line stuff, which is often not a good idea.
You want to encapsulate the whole config input portion of your program so that you can drive it with a command line, config file, other python program, whatever.
So, I would remove any call to add_option from your subclasses.
If you want to discover what your config requirements look like at runtime, I would simply add that data to your subclasses; let each one have a member or method that can be used to figure out what kind of inputs it needs.
Then, you can have an input organizer class walk over them, pull this data out, and use it to drive a command line, config file, or what have you.
But honestly, I've never needed to do this at run time. I usually pull all that config stuff out to it's own separate thing which answers the question "What does the user need to tell the tool?", and then the subclasses go looking in the config data structure for what they need.
Are you sure that subclassing is what you want to do? Your overriding behavior could just be implemented in a function.