I am new to using the python interactive window and I like it but it seems to clear local variables in between runs, so if I run something like
def main():
dates = '2012152'
# %%
print(dates) # want to just run this
# %%
if __name__ == '__main__':
main()
# or even
main()
all at once it works fine but then if I just run the middle cell I get "dates not defined" error. It works outside of the function because apparently a global variable is saved:
dates = '2012152'
# %%
print(dates) # this works if this cell is run
# %%
Is there any way to get a similar behavior inside a function? If not it doesn't seem useful to me at all (maybe I have designed my code badly?).
Cells are a great way to experiment with flat code, but they are limited when working nested inside functions.
One way to work around this is to use a regular built-in python debugger and set a breakpoint within the function.
Here is a process I use for experimenting with code inside a function:
Set a breakpoint in the function, after the code you want to experiment with and start debugging.
Make any necessary changes to the code.
Select the lines that you've changed and that you want to run again. Make sure to include all the indentations as well.
Right-click and select Evaluate in Debug Console.
This will allow you to run the code one line at a time, see results, and make any necessary adjustments as you go along.
The process could be further improved by binding a keyboard shortcut to the this command.
Yes, print(dates) will not run as the dates variable isn't in scope, unless the function main is called and even then dates will be only in the local scope of the function, not in global scope.
So to print it outside the function, you need to first define it.
Related
I have this code:
import sys
def random(size=16):
return open(r"C:\Users\ravishankarv\Documents\Python\key.txt").read(size)
def main():
key = random(13)
print(key)
When I try running the script, there are no errors, but nothing appears to happen. I expected it to print some content from the key file, but nothing is printed.
What is wrong? How do I make the code run?
You've not called your main function at all, so the Python interpreter won't call it for you.
Add this as the last line to just have it called at all times:
main()
Or, if you use the commonly seen:
if __name__ == "__main__":
main()
It will make sure your main method is called only if that module is executed as the starting code by the Python interpreter. More about that here: What does if __name__ == "__main__": do?
If you want to know how to write the best possible 'main' function, Guido van Rossum (the creator of Python) wrote about it here.
Python isn't like other languages where it automatically calls the main() function. All you have done is defined your function.
You have to manually call your main function:
main()
Also, you may commonly see this in some code:
if __name__ == '__main__':
main()
There's no such main method in python, what you have to do is:
if __name__ == '__main__':
main()
Something does happen, it just isn't noticeable
Python runs scripts from top to bottom. def is a statement, and it executes when it is encountered, just like any other statement. However, the effect of this is to create the function (and assign it a name), not to call it. Similarly, import is a statement that loads the other module (and makes its code run top to bottom, with its own global-variable context), and assigns it a name.
When the example code runs, therefore, three things happen:
The code for the sys standard library module runs, and then the name sys in our own module's global variables is bound to that module
A function is created from the code for random, and then the name random is bound to that function
A function is created from the code for main, and then the name main is bound to that function
There is nothing to call the functions, so they aren't called. Since they aren't called, the code inside them isn't run - it's only used to create the functions. Since that code doesn't run, the file isn't read and nothing is printed.
There are no "special" function names
Unlike in some other languages, Python does not care that a function is named main, or anything else. It will not be run automatically.
As the Zen of Python says, "Explicit is better than implicit". If we want a function to be called, we have to call it. The only things that run automatically are the things at top level, because those are the instructions we explicitly gave.
The script starts at the top
In many real-world scripts, you may see a line that says if __name__ == '__main__':. This is not "where the script starts". The script runs top to bottom.
Please read What does if __name__ == "__main__": do? to understand the purpose of such an if statement (short version: it makes sure that part of your top-level code is skipped if someone else imports this file as a module). It is not mandatory, and it does not have any kind of special "signalling" purpose to say where the code starts running. It is just a perfectly normal if statement, that is checking a slightly unusual condition. Nothing requires you to use it in a script (aside from wanting to check what it checks), and nothing prevents you from using it more than once. Nothing prevents you from checking whether __name__ is equal to other values, either (it's just... almost certainly useless).
You're not calling the function. Put main() at the bottom of your code.
I was wondering how can I run only a small part of the code without running all the previous ones, such a thing would be very handy to me because I'm writing code just to see how it works and I do that in the same Python file, so when I want to run just the one I recently wrote it also runs all the previous ones.
I only want to run the highlighted part, not all the previous lines:
you should make all your codes inside functions.
and call it inside the main function.
for example:
# Import necessary libraries.
# Define your functions from the top
def Foo():
print('foo')
def Bar():
print('bar')
if __name__ == '__main__':
# Run your code from here, call the needed functions.
Foo()
Bar()
# If you don't want to run Bar(), simply comment it.
Definitions/ Functions are the best way to go for this.
def afunc():
print('This is the function printed after the other function')
def func(): # Starts the definition
print('This is a function')
afunc()
func() # Runs the Code
I've not used Pycharm specifically, but I know in many other IDEs for python (VS Code, Spyder, Jupyter), you can break out the script into cells and run each cell individually.
For VS Code and Spyder, you desginate different cells by including lines that start with #%%
This will also open up an interactive python shell where you can modify and re-run each section or type out individual lines to run
This is a follow-up question to Stepwise debugging of selected Python code.
Why does import pdb; pdb.set_trace trigger two different debugging scenarios when called differently in Spyder?
Here's the edited sample code in the answer from Carlos Cordoba to the question mentioned above.
The code:
def foo():
names = ['A', 'B', 'C']
values = [11,12,13]
i = 0
import pdb; pdb.set_trace()
for n in names:
variable = str(n) + ' = ' + str(values[i])
print(variable)
i += 1
foo()
Scenario1 - Run file (F5), Continue Execution until next breakpoint (F12) and Run Current Line (F10)
This procedure works just fine. Let me just explain how for the sake of context:
Run file (F5) highlights line 2:
Proceeding with Continue Execution until next breakpoint (F12) takes you directly to line 8. Also notice in the screenshot below that the Variable explorer is populated with the variables i, names and values. Other variables are added and updated as you go through the rest of the code with Run Current Line (F10):
Or you could Continue Execution until next breakpoint (F12) and finish the procedure that way. Doing the former all the way down to foo() clears the variable explorer, prints --Return-- in the ipdb debugger, and exits the debugger.
And I guess I should just go with this way of doing things every time, but I'm very interested in the other options of running code that Spyder offers as well. And I'm particularly fond of defining and running cells with #%% and Ctrl+Enter.
Scenario 2 - Ctrl+Enter in a cell that includes the entire code
Ctrl+Enter within the cell highlights line 8, and populates the Variable Explorer:
Proceeding with Continue Execution until next breakpoint (F12) clears the variable explorer and exits the debugger just like before:
And that's fine too, but here's my case:
Scenario 3 - Running and debugging multiple cells
When I'm debugging fragments of code of bigger data science projects, I often end up defining some variables one place, and wanting to debug functions that use these variables as input somewhere else. And that's why I often end up in the situation below, where I've defined the variables in one cell, and have a For Loop using the same variables in another cell:
Cell that contains variables
Cell that contains For Loop
But hitting Ctrl+Enter and proceeding with Run Current Line (F10) triggers a messy situation within interactiveshell.py:
And now, the questions:
What's going on here?
Can this be avoided?
Why isn't it possible to debug cells (or highlighted code + f9) like this?
Thank you for any suggestions!
(Spyder maintainer here) I think the problem is you're trying to evaluate cells inside the scope of a function. In this case all variables are local to the scope, so you can't evaluate foo in pieces, which is what you're trying to do with our cells.
To achieve what you want, you could use a class instead. That would allow you to save your data in variables shared by all methods in the class and to define the functions/methods you want to manipulate those data. A class would also allow you to have data and functions/methods neatly encapsulated, i.e. without being defined in the global scope of your code.
With that, you could simply run a cell that calls the method you want to debug. In the example you posted above, this will be
# %%
class Foo:
def __init__(self):
self.names = ['A', 'B', 'C']
self.values = [11,12,13]
def manipulation(self):
i = 0
import pdb; pdb.set_trace()
for n in self.names:
variable = str(n) + ' = ' + str(self.values[i])
print(variable)
i += 1
f = Foo()
# %%
f.manipulation()
This allows me to debug the workings of the manipulation method without problems.
I have this code:
import sys
def random(size=16):
return open(r"C:\Users\ravishankarv\Documents\Python\key.txt").read(size)
def main():
key = random(13)
print(key)
When I try running the script, there are no errors, but nothing appears to happen. I expected it to print some content from the key file, but nothing is printed.
What is wrong? How do I make the code run?
You've not called your main function at all, so the Python interpreter won't call it for you.
Add this as the last line to just have it called at all times:
main()
Or, if you use the commonly seen:
if __name__ == "__main__":
main()
It will make sure your main method is called only if that module is executed as the starting code by the Python interpreter. More about that here: What does if __name__ == "__main__": do?
If you want to know how to write the best possible 'main' function, Guido van Rossum (the creator of Python) wrote about it here.
Python isn't like other languages where it automatically calls the main() function. All you have done is defined your function.
You have to manually call your main function:
main()
Also, you may commonly see this in some code:
if __name__ == '__main__':
main()
There's no such main method in python, what you have to do is:
if __name__ == '__main__':
main()
Something does happen, it just isn't noticeable
Python runs scripts from top to bottom. def is a statement, and it executes when it is encountered, just like any other statement. However, the effect of this is to create the function (and assign it a name), not to call it. Similarly, import is a statement that loads the other module (and makes its code run top to bottom, with its own global-variable context), and assigns it a name.
When the example code runs, therefore, three things happen:
The code for the sys standard library module runs, and then the name sys in our own module's global variables is bound to that module
A function is created from the code for random, and then the name random is bound to that function
A function is created from the code for main, and then the name main is bound to that function
There is nothing to call the functions, so they aren't called. Since they aren't called, the code inside them isn't run - it's only used to create the functions. Since that code doesn't run, the file isn't read and nothing is printed.
There are no "special" function names
Unlike in some other languages, Python does not care that a function is named main, or anything else. It will not be run automatically.
As the Zen of Python says, "Explicit is better than implicit". If we want a function to be called, we have to call it. The only things that run automatically are the things at top level, because those are the instructions we explicitly gave.
The script starts at the top
In many real-world scripts, you may see a line that says if __name__ == '__main__':. This is not "where the script starts". The script runs top to bottom.
Please read What does if __name__ == "__main__": do? to understand the purpose of such an if statement (short version: it makes sure that part of your top-level code is skipped if someone else imports this file as a module). It is not mandatory, and it does not have any kind of special "signalling" purpose to say where the code starts running. It is just a perfectly normal if statement, that is checking a slightly unusual condition. Nothing requires you to use it in a script (aside from wanting to check what it checks), and nothing prevents you from using it more than once. Nothing prevents you from checking whether __name__ is equal to other values, either (it's just... almost certainly useless).
You're not calling the function. Put main() at the bottom of your code.
I'm just finding out now that when importing a module, it seems to run through ALL the code, instead of just the one function that I want it to go through. I've been trying to find a way around this, but can't seem to get it. Here is what is happening.
#mainfile.py
from elsewhere import something_else
number = 0
def main():
print('What do you want to do? 1 - something else')
donow = input()
if donow == '1':
something_else()
while 1:
main()
#elsewhere.py
print('I dont know why this prints')
def something_else():
from mainfile import number
print('the variable number is',number)
Now, although this code KIND OF works the way I want it to, the first time when I initiate it, it will go to the main menu twice. For example: I start the program, press one, then it asks me what I want to do again. If I press one again, then it will print "the variable number is 0".
Once I get this working, I would like to be importing a lot of variables back and forth. The only issue is,if I add more import statements to "elsewhere.py" I think it will just initiate the program more and more. If I put "from mainfile import number" on line 1 of "elsewhere.py", I think this raises an error. Are there any workarounds to this? Can I make a different file? What if I made a class to store variables, if that is possible? I'm very new to programming, I would appreciate it if answers are easy to read for beginners. Thank you for the help.
As Jan notes, that's what import does. When you run import, it runs all of the code in the module. You might think: no it doesn't! What about the code inside something_else? That doesn't get run! Right, when the def statement is executed it creates a new function, but it doesn't run it. Basically, it saves the code for later.
The solution is that pretty much all interesting code should be in a function. There are a few cases which make sense to put at the top-level, but if in doubt, put it inside a function. In your particular case, you shouldn't be printing at the top level, if you need to print for some reason, put that into a function and call it when you need it. If you care when something happens, put it in a function.
On a second node, don't import your primary script in other scripts. I.e. if your mainfile.py directly, don't import that in other files. You can but it produces confusing results, and its really best to pretend that it doesn't work.
Don't try to import variables back and forth. Down that path lies only misery. You should only be importing things that don't change. Functions, classes, etc. In any other case, you'll have hard time making it do what you want.
If you want to move variables between places, you have other options:
Pass function arguments
Return values from a function
Use classes
I'll leave it is an exercise to the reader to learn how to do those things.
import executes imported code
import simply takes the Python source file and executes it. This is why it prints, because that instruction is in the code and with import all the instructions get exectued.
To prevent execution of part of imported package/module, you shall use the famous:
if __name__ == "__main__":
print("I do not print with `import`")
Note, that this behaviour is not new in Python 3, it works the same way in Python 2.x too.