I am just a beginner in coding, trying to self teach python, then I got a lot of questions in my mind. so consider I have a main.py with a function def catch_urls(**kwargs): I will pass key:value arguments while running the file. My requirement here is there will be a bunch of arguments I pass to the function of which I need to find out the count of pattern matching keys- that means
main.py type=internal url1=google.com url2=yahoo.com timeout=10s url3=stackoverflow.com
Q1. How to get the count of how many url1, url2, url3, .... is given in arguments ? these url* count will vary on each runs then how to get the count of this pattern keys ? can we do something like psuedo code like count(url*)
Q2. Using **kwargs can I actually get these arguments passed into execution ? or do I need to use some library called "click" or so to get these arguments passed into my function ?
The arguments arrive as strings in sys.argv. So, given your example, sys.argv would be a list containing:
[
"main.py",
"type=internal",
"url1=google.com",
"url2=yahoo.com",
"timeout=10s",
"url3=stackoverflow,.com"
]
You can parse those yourself, or you can use the argparse module to parse them.
It's not usually productive to spent a lot of time optimizing code that only gets used once. You could certainly say:
cnt = sum(i.startswith("url") for i in sys.argv)
**kwargs is used for functions within a program. It's not involved in command line arguments.
Related
Consider you have a function run() decorated as click.command() and multiple click.options() for default values and more specifications. In this run function I want to call my other 'sub' functions of the tool one by one with the given parameters.
#click.command("run")
#click.options(_some_options)
def run(ctx, par1: str, par2: str, par3: int):
ctx.invoke(some_other_func, par1=par1, par2=par2, par3=par3)
This is running and works well so far. But now I'd like to open up the possibility to insert multiple values for the second parameter (par2) as a list of strings and execute the run function for each of the given strings in the list. Imagine an input like:
run(par1 = "hello", par2 = ["man", "woman", "child"], par3 = 3)
Expected Output:
"hello man 3"
"hello woman 3"
"hello child 3"
I tried using a decorator like:
def decorator(func):
#wraps(func)
def run_wrapper(ctx, par1:str, par2:list, par3:int)
run_unwrapped = run.__wrapped__
for var in par2:
run_unwrapped(ctx, par1, par2, par3)
return run_wrapper
and this worked outside of the context of click but with click it doesn't. I read that one should use
the #click.pass_context click.palletsprojects.com/en/7.x/commands/#decorating-commands instead but I have difficulties with this. Especially accessing the given parameters and the multiple calls of "run" just do not work.. Another difficulty is the input of a arbitrary long list - couldn't find a solution for this as well (multiple=True in the slick.options() does not work as I expected..).
Is a wrapper for this task actually a good idea? I thought of using this as I do not want to change my whole code and clutter it with for-loops.. but if there is a better idea I'd be grateful for it!
I'm a beginner with Python and Stack overflow - please be kind :)
I'm trying to use the ast module in Python to parse input code, but am struggling with a lot of the syntax of how to do so. For instance, I have the following code as a testing environment:
import ast
class NodeVisitor(ast.NodeVisitor):
def visit_Call(self, node):
for each in node.args:
print(ast.literal_eval(each))
self.generic_visit(node)
line = "circuit = QubitCircuit(3, True)"
tree = ast.parse(line)
print("VISITOR")
visitor = NodeVisitor()
visitor.visit(tree)
Output:
VISITOR
3
True
In this instance, and please correct me if I'm wrong, the visit_Call will be used if it's a function call? So I can get each argument, however there's no guarantee it will work like this as there are different arguments available to be provided. I understand that node.args is providing my arguments, but I'm not sure how to do things with them?
I guess what I'm asking is how do I check what the arguments are and do different things with them? I'd like to check, perhaps, that the first argument is an Int, and if so, run processInt(parameter) as an example.
The value each in your loop in the method will be assigned to the AST node for each of the arguments in each function call you visit. There are lots of different types of AST nodes, so by checking which kind you have, you may be able to learn things about the argument being passed in.
Note however that the AST is about syntax, not values. So if the function call was foo(bar), it's just going to tell you that the argument is a variable named bar, not what the value of that variable is (which it does not know). If the function call was foo(bar(baz)), it's going to show you that the argument is another function call. If you only need to handle calls with literals as their arguments, then you're probably going to be OK, you'll just look instances of AST.Num and similar.
If you want to check if the first argument is a number and process it if it is, you can do something like:
def visit_Call(self, node):
first_arg = node.args[0]
if isinstance(first_arg, ast.Num):
processInt(first_arg.n)
else:
pass # Do you want to do something on a bad argument? Raise an exception maybe?
I'm working on a project where I am making a command line to learn how to use curses in Python. I am starting to work on the interpreter for the commands, but have a situation I want to see if there is a better solution.
I want to split the string input into a command and arguments. Here's an example of how I could do it:
def processor(inputText):
command, arguments=inputText.split(' ')[0], inputText.split(' ')[1:]
I could do it this way, but because I'm picky/weird I don't like having inputText.split(' ') twice. Here's another option I could choose to shorten it:
def processor(inputText):
inputTextSplit=inputText.split(' ')
command, arguments=inputTextSplit[0], inputTextSplit[1:]
Since we're shortening code, inputTextSplit is longer so replacing it with i could be 'better':
def processor(inputText):
i=inputText.split(' ')
command, arguments=i[0], i[1:]
My issue with this though, is using shorter variables like i could cause overwriting other variables later (like using i in a for loop like for i in array:). This would make code look cleaner, but at the same time could cause issues if not careful.
Is there a way to take sections of splits of an array to variables? For example, in TI-Basic you can pass a list as an argument for an operation. To get multiple outputs of a graph function in TI-Basic would look like:
"If Y₁ is 2x, then the results would be as follows:"
Y₁({1, 3})
"{2, 6}"
{Y₁(1), Y₁(3)}
"{2, 6}"
Is there a similar way to do something hypothetical like this:
def processor(inputText):
command, arguments=inputText.split(' ')[[0,1:]]
Is there some advanced Python technique that can accomplish this, or is just an lazy idea? The expected result for an input like 'command arg1 arg2' would be ['command', ['arg1', 'arg2']].
This concept isn't something I want to limit to my project example, either. Another example could be array[[0,1:6,7:8,9:]] which would give another array with 4 values, parts of the original.
Also, I am on Python 2.7. Thanks in advance for your advice.
You can simply do:
def processor(inputText):
command, *arguments = inputText.split(' ')
return command, arguments
print(processor('command arg1 arg2 arg3'))
# ('command', ['arg1', 'arg2', 'arg3'])
Using *arguments will assign all remaining parts of the list generated by split, after the first one has been assigned to command, to the arguments list.
You can have a look at PEP 3132 -- Extended Iterable Unpacking for details on this syntax.
I'm doing a bunch of unit tests for a bunch of methods I have in my code and started to realize I could really condense this code block down if I could do some sort of macro that would just take care of all my insertions for me.
This is an example of a method I would use, however the only differences is the parameters c_unit_case also c_test_case are based on the methods in lib.
def test_case(filepath):
tests = parsedfile(filepath)
for unittests in tests:
print lib.c_test_case(unittests.params[0])
I'm looking for something sort of like this.
GENERIC_CASE(method_name, params, filepath)
(tests) = parsedfile(filepath)
for unittests in (tests):
args += unittests.(params)
print lib.(method_name)(args)
Is it possible to do this type of thing in Python?
Try something like this and see if this works:
def test_case(method_name, filepath, *args):
tests = parsedfile(filepath)
print (method_name(*args))
*args in the signature of the function lets you put in as many additional arguments as you'd like. Calling method_name(*args) unrolls the arguments into the parameter.
This should handle a variable number of arguments.
This is what it would sort of look like the way you had it:
GENERIC_CASE(method_name, filepath, *params)
(tests) = parsedfile(filepath)
for unittests in (tests):
args += unittests.(*params)
print lib.(method_name)(args)
I'm not 100% if this is what you're looking for.
Now i use twisted.soap to build my soap server, I'd like to build a function with plural arguments like this:
def soap_searchFlight(self,name=None,startpoint=None,destination=None):
d=Deferred()
d.addCallback(functions.searchFlight)
d.addErrback(functions.failure)
print "name"+name
print "startpoint"+startpoint
print "destination"+destination
requestdic={"name":name,"startpoint":startpoint,"destination":destination}
print requestdic
d.callback(requestdic)
return d.result
and I wrote a script to test :
import SOAPpy
import twisted
p = SOAPpy.SOAPProxy('http://localhost:7080/')
p.config.dumpSOAPOut=1
p.config.dumpSOAPIn=1
print p.searchFlight(name='3548',startpoint="北京飞机场",destination="上海飞机场")
It gives me back like this:
name上海飞机场
startpoint北京飞机场
destination3548
it looks like the args order are totally wrong so what happens and how can i ensure the right order ?
Without seeing functions.searchFlight, it's a little hard to tell, but it appears that you're passing a dict to in in a callback, then assuming that the items in the dict are in a particular order (they're not).
Change the signature of functions.searchFlight to take a tuple, and call it with a tuple in the order you want. (or pass in an ordered dict...or don't assume the dict's items are in the order that you created it in).