Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have a method I call from the command line using argparse. I also want to call that method from another method, in this case I get an error saying args is not defined. Is there a way around this, I have tried setting a default but I get the same error.
def change_modem_bank(bank_num=None, modem=None):
if args.sim_bank and args.modem_num:
bank_num = args.sim_bank
modem = args.modem_num
if "1" in bank_num:
print "2"
elif "2" in bank_num:
print "2"
print modem
if __name__=='__main__':
parser_mode = subparsers.add_parser('set_modem_bank')
parser_mode.add_argument('-bank',dest='sim_bank',help='SIM bank number',nargs='?',const=None,default=None)
parser_mode.add_argument('-modem_num',dest='modem_num',help='Modem number',nargs='?',const=None,default=None)
parser_mode.set_defaults(func=change_modem_bank)
args=parser.parse_args()
args.func()
I want to call the method like so from another script:
import cellular_modem
cellular_modem.change_modem_bank("2","0")
Currently I can call it like this:
myscript.py set_modem_bank -bank ${num} -modem ${modem_num}
I would like it to work with either type of call, from CLI and from inside a python script.
When you call it as a script, what happens is:
args=parser.parse_args()
change_modem_bank() # equivalent to args.func()
When you import the module, that main part is skipped, so args is not set. If you want to call change_modem_back as is, then you need to create an args variable that looks like the one that the parser would generate. Here's one way of doing that:
import cellular_modem
import argparse
args = argparse.Namepspace(simbank=xxx, modem_num=xxx)
cellular_modem.change_modem_bank("2","0")
Your function assumes that, in its global argument space there is an object with these 2 attributes:
args.sim_bank, args.modem_num
You change the function to something like:
def change_modem_bank(bank_num=None, modem=None, args=None):
if args and args.sim_bank and args.modem_num:
bank_num = args.sim_bank
modem = args.modem_num
and invoke it in the main as:
args.func(args=args)
This way it is clear where the function is getting its args variable from. It also behaves rationally when args is a simple default value like None.
One way or other you need to initialize an args variable when importing, and then write your function is a way that it will be ok with that default version.
Your change_modem_bank function tries to access args directly, which works when you call it as a command-line script since it's in the module namespace then, but fails when you call it separately. Just fix it to get args passed in instead:
def change_modem_bank(bank_num, modem):
if "1" in bank_num:
print "2"
elif "2" in bank_num:
print "2"
print modem
And call it with:
args.func(args.sim_bank, args.modem_num)
You'll have to figure out what your function is supposed to do if the arguments are None, since that will cause an error now.
Related
I want to set breakpoints in different places of my program. However they are fired if I pass a specific argument to my program, I called it STOP_LEVEL
STOP_LEVEL = 0
def mbp(sl=-1):
if sl == STOP_LEVEL:
# I would like to print which function called this
mlog.info("break point at %s, %s", ...)
breakpoint()
Then I can create a breakpoint like
mbp(2)
and if I set stop_level to 2, it's fired.
First, I would like to know are there other standard methods for such functionality? Second, I would like to know where from my mbp function was called, I mean the caller function, filename and line number. How can I include them in my function as logging information?
There isn't built in functionality like that.
The only way to find where your application was called from would be to examine the stack or to pop from your function. After popping the stack (returning from your function) you'll be at the location in your code it was called from.
To examine the stack you can use inspect.stack()
In pdb you can run the command where
I ended up to this function:
import sys
STOP_LEVEL = 0
def mbp(sl=-1):
if sl == STOP_LEVEL:
fname = sys._getframe().f_back.f_code.co_name
line = sys._getframe().f_back.f_lineno
mlog.info("break point at %s line %s",fname, line)
breakpoint()
This question already has answers here:
python print all function calls to know the script flow
(2 answers)
Closed 1 year ago.
What specific syntax needs to be added to the code below in order to print out the full trace of the chain of function calls that result in each time that four.myFunction() gets called in the code sameple below?
one.py
import two
import three
two.twoFunction()
three.threeFunction()
two.py
import four
def twoFunction():
four.myFunction()
three.py
import four
def threeFunction():
four.myFunction()
four.py
def myFunction():
print("trace of which functions called me, back to original.")
This is important because we have functions that seem to be run more times than the code looks like the functions should be run.
If we can isolate the chain of calling scripts/functions for each call to four.myFunction(), we will be able to more closely diagnose what might be going on.
We are using Python 3.
With each of your functions, you can require an input like def ...(past_calls):and add the current function to it when calling another.
i.e.
def NthFunction(past_calls):
# Call next function, adding current to the trace.
NextFunction(past_calls + [n])
And when you are printing your results, you can use the information given as the parameter (you can also add more details if need be).
How can I run a python function from an AHK script? If it's possible, how would I:
Pass arguments to the python function?
Return data from the python function back to my running AHK script?
The only relevant information I could find was this answer, however I could not manage to implement it into my own script.
My best attempt at implementing this is the following snippet of code:
e::; nothing, because RunWait it's the command recommended in the question that I linked, so that means that I have to do a RunWait every time I press e?
There is no native way to do this, as the only interaction AHK can do with Python is to run an entire script. However, you can modify the python script to accept arguments, then you can interact between the scripts (like the linked question).
The solution is as follows- similar to the question you linked, set up the python script so that it takes the function name and function parameters as arguments, then have it run the function with those arguments.
Similar to my answer on the linked question, you can use sys.argv to do this:
# Import the arguments from the sys module
from sys import argv
# If any arguments were passed (the first argument is the script name itself, so you must check for >1 instead of >0)
if len(argv) > 1:
# This next line is basically saying- If argv is longer than 2 (the script name and function name)
# Then set the args variable to everything other than the first 2 items in the argv array
# Otherwise, set the args variable to None
args = argv[2:] if len(argv) > 2 else None
# If arguments were passed, then run the function (second item in argv) with the arguments (the star turns the list into args, or in other words turns the list into the parameter input format)
# Otherwise, run the function without arguments
argv[1](*args) if args else argv[1]()
# If there is code here, it will also execute. If you want to only run the function, then call the exit() function to quit the script.
Then, from AHK, all you would need to do is run the RunWait or Run command (depending on whether you want to wait for the function to finish) to call the function.
RunWait, script.py "functionName" "firstArgument" "secondArgument"
The second part of your question is tricky. In the question you linked, there is a nice explanation on how to return integer values (TLDR: use sys.exit(integer_value)), however if you want to return all sorts of data, like strings, for example, then the problem becomes more confusing. The thing is that at this point, I think the best solution is to write the output to a file, then have AHK read the file after the Python script is done executing. However, if you're already going to go down the "write to a file, then read it" route, then you might as well have already done that from the start and used that method to pass the function name and arguments to the python script.
This question already has answers here:
Why doesn't the main() function run when I start a Python script? Where does the script start running (what is its entry point)?
(5 answers)
Closed 5 months ago.
Consider:
#! /usr/bin/python
def main():
print("boo")
This code does nothing when I try to run it in Python 3.3. No error or anything.
What’s wrong?
gvim script
chmod 775 script
./script
You still have to call the function.
def main(): # declaring a function just declares it - the code doesn't run
print("boo")
main() # here we call the function
I assumed you wanted to call the print function when the script was executed from the command line.
In Python you can figure out if the script containing a piece of code is the same as the script which was launched initially by checking the __name__ variable against __main__.
#! /usr/bin/python
if __name__ == '__main__':
print("boo")
With just these lines of code:
def main():
print("boo")
you're defining a function and not actually invoking it. To invoke the function main(), you need to call it like this:
main()
You need to call that function. Update the script to:
#! /usr/bin/python
def main():
print("boo")
# Call it
main()
In Python, if you want to write a script to perform a series of small tasks sequentially, then there is absolutely no need to write a function to contain them.
Just put each on a line on its own; or use an expression delimiter like ; (not really recommended, but you can do is you so desire), likewise:
task1
task2
task3
task4
or
task1; task2; task3; (again **not** really recommended, and certainly not pythonic)
In your case your code could be turned to something like:
print('boo')
print('boo2')
print('boo3')
and it would still act as you expect it to, without the main() method, as they get evaluated sequentially.
Please note that the reason you might want to create a function for these series of tasks is:
to present a nice interface (to clients of the code),
or to encapsulate repeated logic
There might be more uses, but that's the first I can come up with, and serve to prove my point.
Now, if you feel compelled to write code that resembles the main() method in other programming languages, then please use the following Python idiom (as stated by other users so far):
if __name__ == '__main__':
doSomething()
The above is working as follows:
When you import a Python module, it gets a string (usually, the name under which it was imported) assigned as its __name__ attribute.
When you execute a script directly (by invoking the Python vm and passing it the script's name as an argument), the __name__ attribute is set to __main__
So when you use the above idiom, you can both use the script as a pluggable module by importing it at will, or just execute it directly to have the series of expressions under the if __name__ == '__main__': be evaluated directly.
Should you feel the need to dig through more information, my sources were the following:
Python documentation: Modules
Python documentation: Executing modules as scripts
Python documentation: The data model (search for __name__)
If you find the other answers confusing or intimidating, here's a parable which should hopefully help. Look at the following Python program:
a = 34
When it runs, it does something: before exiting the script, Python learns that there is a variable a and that its value is the integer 34. It doesn't do anything with this information, but it's a complete program which does something. In order for it to produce some actual value, it needs to interact with its environment, though. What does it do with this value? It could create 34 directories, or ping the 34th server in your data center, or check the strength of the passwords of the newest 34 users in your database, or whatever; or just print something.
a = 34
print(a)
The following program is in some sense very similar to the first one.
def b():
a = 34
print(a)
When you run this program, it does something: Python now knows that there is a function named b, and that it doesn't take any arguments, and that it contains some syntactically valid Python code which will be run when some other code calls it, but it doesn't actually do anything with this code yet. In order to observe any value being produced by the code in the function, you have to actually call it:
b()
(As an aside, maybe also note that the local variable a inside the function declaration b is distinct from the global variable with the same name.)
i want to point, that i am learning python since short time.
The question is going be to beginner one.
I need to add command to menu at top of program, which would call function "color_picker("red").
kolory.add_command(label="Czerwony", command=color_picker('red'))
When i am using that, its somehow wrong, cuz its called once the program started, its not waiting for me to click the menu button. (i am sure of it, as i added "showinfo" to that function, and it shows the message before i do anything)
kolory.add_command(label="Czerwony", command=lambda: color_picker('red')) That one kinda works, but i don't know what does "lambda" mean here. Is it only way to call functions with arguments under menu options?
Same question goes to binding keyboard shortcuts.
okno.bind("1", color_picker) - that will call the function but does not have the argument, which should be a color. How can i do that?
So, how to assign functions WITH arguments, to keyboard shortcuts and to menu using add_command?
PS. Was searching trough google, but it seems python does not have so good documentation like c# does for example. Or i am too stupid to find it.
EDIT:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
TypeError: color_picker() takes at most 1 argument (2 given)
Thats the error message, when i try to use "pick_red" in okno.bind
I'm not sure if I understand the question, but here goes;
The problem is that you are calling the color_picker function (by adding () after the function name).
What you want to do is pass the actual function, not the result of the function call as the command keyword argument, e.g. add_command(label="Czerwony", command=color_picker)
However, since you want to give it a fixed argument 'red', you must use partial from functools, something like;
from functools import partial
pick_red = partial(color_picker, "red")
kolory.add_command(label="Czerwony", command=pick_red)
EDIT:
Now that your error message shows that you are using Tkinter, we can see that according to documentation the function that is given to bind() is always passed an event parameter, so you need a function that can accept it;
def pick_red_with_event(event):
# We really do nothing with event for now but we always get it...
color_picker("red")
okno.bind("1", pick_red_with_event)
Same thing works for okno.bind, if you have defined pick_red as above, just do:
okno.bind("1", pick_red)