Parsing arguments in python - python

I have a question about parsing arguments in python. Example code below.
Class Parser:
def __init__(self):
self.args = argparse.ArgumentParser()
self.args.add_argument("--email")
self.args.add_argument("--file")
self.args.add_argument("--save")
self.args.add_argument("--time")
self.args_parsed = self.args.parse_args()
def get_email(self):
return self.args_parsed.email
def get_file(self):
return self.args_parsed.file
def get_save(self):
return self.args_parsed.save
def get_time(self):
return self.args_parsed.time
Class functions(Parser):
def __init__(self):
super().__init__()
def Function1(self):
pass
def Function2(self):
pass
def Function3(self):
pass
def Function4(self):
pass
if __name__ == '__main__':
try:
arguments = sys.argv[1:]
if "--file" in arguments:
Function1()
elif "--save" in arguments:
Function2()
elif "--email" in arguments:
Function3()
elif "--time" in arguments:
Function4()
except IndexError:
print("Invalid argument")
Basically what my question is I want to add a lot more options then I already have, and I would have to keep on continuing the if elif chain. Is there a way to reduce this to only parse the arguments the user chooses? thanks
I know that you can do something like this:
my_dict = {
"file": Function1,
"save": Function2,
"email": Function3,
"time": Function4
}
if __name__ == '__main__':
try:
arguments = sys.argv[1]
if arguments:
my_dicts[arguments]()
But how can I do that with multiple values? Thanks

Welcome to Stack Overflow! Like the other commenters have said it's difficult to help you because there's a lot of different things you could do depending on what you intend to do beyond the code you showed us. In the future, I would suggest that you read how to ask a good question
That being said, here's something that could help you:
#!/usr/bin/env python3
import argparse
def email_handler(email_argument):
print(f'The email {email_argument} has been chosen')
def file_handler(file_argument):
print('I have to do something different with this file:',
file_argument)
def save_handler(save_argument):
print('Maybe you want to save', save_argument)
def time_handler(time_argument):
print(f'We have to take time {time_argument} into account')
options_handlers = {
'email' : email_handler,
'file' : file_handler,
'save' : save_handler,
'time' : time_handler
}
parser = argparse.ArgumentParser()
for current_option in options_handlers:
parser.add_argument(f'--{current_option}')
arguments_extracted = parser.parse_args()
arguments_accessible = vars(arguments_extracted)
for (current_argument, current_value) in arguments_accessible.items():
if current_value is not None:
current_handler = options_handlers[current_argument]
current_handler(current_value)
Does that answer some of your questions?

Related

Creation of Classes?

I am new in python and trying to figure out how to modularize my functions. My project is a unit testing framework for Restful APIs. For brevity I've simplified the code.
type_parser.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--type', help='a or b')
args = parser.parse_args()
def A(func):
def return_func():
if args.type == "b":
return func()
else:
pass
return return_func
def B(func):
def return_func():
if args.type == "a":
return func()
else:
pass
return return_func
api_funcs.py
from type_parser import *
class ApiFunctions:
#A
def login():
print "cool"
#B
def logout()
print "not cool"
main.py
from api_funcs import *
api = ApiFunctions()
def __main__():
api.login()
api.logout()
__main__()
CLI
python main.py --type=a
Outcome
Expected:
cool
Actual:
TypeError: return_func() takes no arguments
It works if I take api functions out of a class and call it straight up, but I would want to make it more abstract since there will be 3 sets of APIs
Update - I figured out the answer
class ApiFunctions:
#A
def login(self):
print "cool"
#B
def logout(self)
print "not cool"
def A(func):
def return_func(self):
if args.type == "b":
return func(self)
else:
pass
return return_func
In python the object itself has to be explicitely part of method singature.
Thus you need to write:
def login(self):
Writing self.login is kinda like ()* writing login(self). Since login() takes no argument you get an error.
(*) said kinda like, don't write it
api_funcs.py
from type_parser import *
class ApiFunctions:
#A
def login(self):
print "cool"
#B
def logout(self)
print "not cool"

How to test function, that has two or more input()'s inside?

I need to test some python 3 code, and I got stuck testing function with few input()'s.
Example:
def two_answers():
if input("Input 'go' to proceed") != "go":
return two_answers()
else:
while input("Input 'bananas' to proceed") != "bananas":
print("What?!")
print("You've just gone bananas!")
For functions with one input i use:
def test_some_function(self):
codefile.input = lambda x: 'u'
codefile.some_function() . . . .
And then:
def teardown_method(self, method):
codefile.input = input
To revert inputs back.
But here it won't work. Help!
Here is my solution:
class SimulatedInput:
def __init__(self,*args):
self.args = iter(args)
def __call__(self,x):
try:
return next(self.args)
except StopIteration:
raise Exception("No more input")
Then you could use it like you did before:
def test_some_function(self):
codefile.input = SimulatedInput("u","v")
codefile.some_function() . . . .
What you want is to simulate the user inputs.
You have to use a unittest.mock and patch the input function.
See the Quick Guide.
I would wrap the input in to a function.
def input_wrap(prompt):
return input(prompt)
Then you can inject it.
def two_answers(input_func):
if input_func('...') != 'go':
return two_answers(input_func)
...
Now when you want to test it you can inject a fake or a mock:
def test_two_answers(self):
fake_input = mock.MagicMock()
fake_input.side_effect = ['go', 'foo', 'bananas']
two_answers(fake_input) # no assertion for needed since there's no return value
Later in the code that executes two_answers you call it like this:
two_answers(input_wrap)
A minimalistic example with no dependencies. Play with it to extend it as you wish:
import sys
import io
def two_answers():
if input("Input 'go' to proceed") != "go":
return two_answers()
else:
while input("Input 'bananas' to proceed") != "bananas":
print("What?!")
print("You've just gone bananas!")
def wrapper():
lines = ["go", "bananas"]
def fake_input(*args, **kwargs):
return lines.pop(0)
global input
real_input = input
input = fake_input
two_answers()
input = real_input
wrapper()

Returning values from callback(s) in Python

I am currently looking at trying to use a callback in Python.
What I would like to do is return a value from the callback and then use this return value for conditional processing. So for example if the user enters "Y" I would like to print something to the console.
As I am new to Python the code below is as close as I can get currently but:
a) I am not sure if it is the Pythonic way of doing it
b) the correct way of doing it?
class Observable:
def subscribe(self,callback):
self.callback = callback
def fire(self):
self.callback()
class CallBackStuff:
def doCallback(self):
userInput = raw_input("Please enter Y or N?")
return userInput
if __name__ == '__main__':
s = CallBackStuff()
o = Observable()
o.subscribe(s.doCallback)
t = o.fire()
print t
The easiest way I can think of to do this in your code is to just store the input as
a variable in the CallBackStuff object. Then after you've called the call-back function, you can just access the input data from the CallBackStuff instance. Example below.
class Observable:
def subscribe(self,callback):
self.callback = callback
def fire(self):
self.callback()
class CallBackStuff:
storedInput = None # Class member to store the input
def doCallback(self):
self.storedInput = raw_input("Please enter Y or N?")
if __name__ == '__main__':
s = CallBackStuff()
o = Observable()
o.subscribe(s.doCallback)
o.fire()
print s.storedInput # Print stored input from call-back object
class Observable(object):
def __call__(self, fun):
return fun()
class Callback(object):
def docallback(self):
inp = raw_input()
return inp
if __name__ == "__main__":
print Observable()(Callback().docallback)

Passing arguments through QtGui.QAction to the triggered method

Let's say I have a method like:
def open(self, opt):
if opt == True:
...
if opt == False:
...
how do I pass the argument to it with QtGui.QAction like:
self.openAct = QtGui.QAction("O&pen", self, shortcut="Ctrl+O",
statusTip="Opens a location", triggered=self.open)
I found the answer it is from functools import partial. It was in This thread.

Using a dictionary to select function to execute

I am trying to use functional programming to create a dictionary containing a key and a function to execute:
myDict={}
myItems=("P1","P2","P3",...."Pn")
def myMain(key):
def ExecP1():
pass
def ExecP2():
pass
def ExecP3():
pass
...
def ExecPn():
pass
Now, I have seen a code used to find the defined functions in a module, and I need to do something like this:
for myitem in myItems:
myDict[myitem] = ??? #to dynamically find the corresponding function
So my question is, How do I make a list of all the Exec functions and then assign them to the desired item using the a dictionary? so at the end I will have myDict["P1"]() #this will call ExecP1()
My real problem is that I have tons of those items and I making a library that will handle them so the final user only needs to call myMain("P1")
I think using the inspect module, but I am not so sure how to do it.
My reason to avoid:
def ExecPn():
pass
myDict["Pn"]=ExecPn
is that I have to protect code as I am using it to provide a scripting feature within my application.
Simplify, simplify, simplify:
def p1(args):
whatever
def p2(more args):
whatever
myDict = {
"P1": p1,
"P2": p2,
...
"Pn": pn
}
def myMain(name):
myDict[name]()
That's all you need.
You might consider the use of dict.get with a callable default if name refers to an invalid function—
def myMain(name):
myDict.get(name, lambda: 'Invalid')()
(Picked this neat trick up from Martijn Pieters)
Simplify, simplify, simplify + DRY:
tasks = {}
task = lambda f: tasks.setdefault(f.__name__, f)
#task
def p1():
whatever
#task
def p2():
whatever
def my_main(key):
tasks[key]()
Not proud of it, but:
def myMain(key):
def ExecP1():
pass
def ExecP2():
pass
def ExecP3():
pass
def ExecPn():
pass
locals()['Exec' + key]()
I do however recommend that you put those in a module/class whatever, this is truly horrible.
If you are willing to add a decorator for each function, you can define a decorator which adds each function to a dictionary:
def myMain(key):
tasks = {}
def task(task_fn):
tasks[task_fn.__name__] = task_fn
#task
def ExecP1():
print(1)
#task
def ExecP2():
print(2)
#task
def ExecP3():
print(3)
#task
def ExecPn():
print(4)
tasks['Exec' + key]()
Another option is to place all the functions under a class (or in a different module) and use getattr:
def myMain(key):
class Tasks:
def ExecP1():
print(1)
def ExecP2():
print(2)
def ExecP3():
print(3)
def ExecPn():
print(4)
task = getattr(Tasks, 'Exec' + key)
task()
# index dictionary by list of key names
def fn1():
print "One"
def fn2():
print "Two"
def fn3():
print "Three"
fndict = {"A": fn1, "B": fn2, "C": fn3}
keynames = ["A", "B", "C"]
fndict[keynames[1]]()
# keynames[1] = "B", so output of this code is
# Two
You can just use
myDict = {
"P1": (lambda x: function1()),
"P2": (lambda x: function2()),
...,
"Pn": (lambda x: functionn())}
myItems = ["P1", "P2", ..., "Pn"]
for item in myItems:
myDict[item]()
This will call methods from dictionary
This is python switch statement with function calling
Create few modules as per the your requirement.
If want to pass arguments then pass.
Create a dictionary, which will call these modules as per requirement.
def function_1(arg):
print("In function_1")
def function_2(arg):
print("In function_2")
def function_3(fileName):
print("In function_3")
f_title,f_course1,f_course2 = fileName.split('_')
return(f_title,f_course1,f_course2)
def createDictionary():
dict = {
1 : function_1,
2 : function_2,
3 : function_3,
}
return dict
dictionary = createDictionary()
dictionary[3](Argument)#pass any key value to call the method
#!/usr/bin/python
def thing_a(arg=None):
print 'thing_a', arg
def thing_b(arg=None):
print 'thing_b', arg
ghetto_switch_statement = {
'do_thing_a': thing_a,
'do_thing_b': thing_b
}
ghetto_switch_statement['do_thing_a']("It's lovely being an A")
ghetto_switch_statement['do_thing_b']("Being a B isn't too shabby either")
print "Available methods are: ", ghetto_switch_statement.keys()
Often classes are used to enclose methods and following is the extension for answers above with default method in case the method is not found.
class P:
def p1(self):
print('Start')
def p2(self):
print('Help')
def ps(self):
print('Settings')
def d(self):
print('Default function')
myDict = {
"start": p1,
"help": p2,
"settings": ps
}
def call_it(self):
name = 'start'
f = lambda self, x : self.myDict.get(x, lambda x : self.d())(self)
f(self, name)
p = P()
p.call_it()
class CallByName():
def method1(self):
pass
def method2(self):
pass
def method3(self):
pass
def get_method(self, method_name):
method = getattr(self, method_name)
return method()
callbyname = CallByName()
method1 = callbyname.get_method(method_name)
```
def p1( ):
print("in p1")
def p2():
print("in p2")
myDict={
"P1": p1,
"P2": p2
}
name=input("enter P1 or P2")
myDictname
You are wasting your time:
You are about to write a lot of useless code and introduce new bugs.
To execute the function, your user will need to know the P1 name anyway.
Etc., etc., etc.
Just put all your functions in the .py file:
# my_module.py
def f1():
pass
def f2():
pass
def f3():
pass
And use them like this:
import my_module
my_module.f1()
my_module.f2()
my_module.f3()
or:
from my_module import f1
from my_module import f2
from my_module import f3
f1()
f2()
f3()
This should be enough for starters.

Categories

Resources