Sometimes I'll be working with, say, a list of thousands of items in IDLE, and accidently print it out to the shell. When this happens, it crashes or at least very significaly slows down IDLE. As you can imagine, this is extremely inconvenient.
Is there a way to make it, rather than printing the entire thing, just give me a summarised [1, 2, ...] output?
Any help would be much appreciated.
As above, try a custom print function like:
def my_print(obj):
if hasattr(obj, '__len__') and len(obj) > 100:
print '... omitted object of %s with length %d ...' % (type(obj), len(obj))
else: print obj
Use IPython as shell instead.
You could use custom print function.
In Python 3, since print is a function, you should be able to "override" it. (I don't have it installed so I can't try it out to make sure.) Probably not recommended for real applications but if you're just trying things out, it would be okay I suppose.
It would go something like:
def myprint(*args):
# write the function as described by other people
print = myprint
The Squeezer extension for IDLE was written to do just this. From the description on Pypi:
IDLE can hang if very long output is printed. To avoid this, the Squeezer
extensions catches any output longer than 80 lines of text (configurable) and
displays a rectangular box instead:
Squeezer, and many other IDLE extensions are included in IdleX.
Related
So I'm pretty new to both coding and this website, so please bear with me if this is stupid:
I'm working on a personal project and would like to find a way to clear "print()" statements in python 3.6. For example:
print("The user would see this text.")
but if I continue
print("The user would see this text.")
print("They would also see this text.")
Is there a way to make it so a user would only see the second print statement?
I have seen "os.system('cls')" and "os.system('clear')" recommended, but I get these errors for each:
os.system('cls')
resulting in
sh: 1: cls: not found
and
os.system('clear')
resulting in
TERM environment variable not set.
Obviously I'm missing something, but if you know what it'd be much appreciated. If you know of another way to do what I'm thinking, that would also be awesome. Thank you for taking the time to read this, and thanks for any help.
Edit: I'm using Repl.it as my IDE. Could this be an issue with that site specifically?
Edit: Downloaded a new IDE to check, and the reply worked. If you are new and using Repl.it, be aware that some code does not function properly.
The method that I've used in the past to 'reprint' something on an existing line is to make use of the standard output directly, coupled with a carriage return to bring the printed statement's cursor back to the start of the line (\r = carriage return), instead of relying on the print function.
In pseudocode:
# Send what you want to print initially to standard output, with a carriage return appended to the front of it.
# Flush the contents of standard output.
# Send the second thing you want to print to standard output.
A working example in Python:
import sys
sys.stdout.write('\rThe user would see this text')
sys.stdout.flush()
sys.stdout.write('\rThe user would also see this text')
Edit
Figured I'd add an example where you can actually see the code working, since the working example above is going to execute so quickly that you'll never see the original line. The below code incorporates a sleep so that you can see it print the first line, wait, then reprint the line using the second string:
import sys
from time import sleep
sys.stdout.write('\rThe user would see this text')
sys.stdout.flush()
sleep(2)
sys.stdout.write('\rThe user would also see this text')
Okay, so let me just say beforehand: I am new to Python. I was just experimenting with IDLE and then I had this weird "crash". I put "crash" inside speech marks because I'm not sure if it qualifies as a crash, as rather than the program just crashing the way a normal program would in Windows, it still runs, but whenever I press enter and try and get it to accept new text it doesn't do anything. E.g. if you try and type "print('a')" and then hit enter it just goes to the next line (and doesn't print 'a'). I tried to make a simple function which converted an integer to a string where each character in the string was either a '1' or a '0', forming the binary number representing said (unsigned) integer.
>>> def int_to_str(int_in):
str_out=''
bit_val=1<<int_in.bit_length()
while(int_in>0):
if(int_in>bit_val):
str_out+='1'
int_in-=bit_val
else:
str_out+='0'
bit_val>>=1
return str_out
>>> print('a')
print('c')
Basically, it becomes completely unresponsive to my input, and allows me to edit/change "print('a')" even though I shouldn't be able to if it had actually "accepted" my input. Why is this? What have I done wrong/messed up?
Also, I made sure it isn't something else I was previously messing around with by closing the shell and opening it again and only putting in said code for the "int_to_string" function, and I haven't changed any settings or imported any modules before hand or anything like that (in case it matters).
EDIT: I tried reinstalling, and that helped a bit in that I can now do other stuff fine, but the moment I try to use the "str_to_int()" function, it has this same weird behaviour of not accepting/interpreting any more user input.
Your while loop never terminates, you need to re-arrange your logic. Printing variables can be an effective debugging tool - like this:
>>> def int_to_str(int_in):
str_out=''
bit_val=1<<int_in.bit_length()
while(int_in>0):
print(int_in, bit_val)
if(int_in>bit_val):
str_out+='1'
int_in-=bit_val
else:
str_out+='0'
bit_val>>=1
return str_out
If your program seems to be going on too long you can stop it with ctrl-c.
The print used to be a statement in Python 2, but now it became a function that requires parenthesis in Python 3.
Is there anyway to suppress these parenthesis in Python 3? Maybe by re-defining the print function?
So, instead of
print ("Hello stack over flowers")
I could type:
print "Hello stack over flowers"
Although you need a pair of parentheses to print in Python 3, you no longer need a space after print, because it's a function. So that's only a single extra character.
If you still find typing a single pair of parentheses to be "unnecessarily time-consuming," you can do p = print and save a few characters that way. Because you can bind new references to functions but not to keywords, you can only do this print shortcut in Python 3.
Python 2:
>>> p = print
File "<stdin>", line 1
p = print
^
SyntaxError: invalid syntax
Python 3:
>>> p = print
>>> p('hello')
hello
It'll make your code less readable, but you'll save those few characters every time you print something.
Using print without parentheses in Python 3 code is not a good idea. Nor is creating aliases, etc. If that's a deal breaker, use Python 2.
However, print without parentheses might be useful in the interactive shell. It's not really a matter of reducing the number of characters, but rather avoiding the need to press Shift twice every time you want to print something while you're debugging. IPython lets you call functions without using parentheses if you start the line with a slash:
Python 3.6.6 (default, Jun 28 2018, 05:43:53)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: var = 'Hello world'
In [2]: /print var
Hello world
And if you turn on autocall, you won't even need to type the slash:
In [3]: %autocall
Automatic calling is: Smart
In [4]: print var
------> print(var)
Hello world
Use Autohotkey to make a macro. AHK is free and dead simple to install. www.autohotkey.com
You could assign the macro to, say, alt-p:
!p::send print(){Left}
That will make alt-p put out print() and move your cursor to inside the parens.
Or, even better, to directly solve your problem, you define an autoreplace and limit its scope to when the open file has the .py extension:
#IfWinActive .py ;;; scope limiter
:b*:print ::print(){Left} ;;; I forget what b* does. The rest should be clear
#IfWinActive ;;; remove the scope limitation
This is a guaranteed, painless, transparent solution.
No. That will always be a syntax error in Python 3. Consider using 2to3 to translate your code to Python 3
The AHK script is a great idea. Just for those interested I needed to change it a little bit to work for me:
SetTitleMatchMode,2 ;;; allows for a partial search
#IfWinActive, .py ;;; scope limiter to only python files
:b*:print ::print(){Left} ;;; I forget what b* does
#IfWinActive ;;; remove the scope limitation
I finally figured out the regex to change these all in old Python2 example scripts. Otherwise use 2to3.py.
Try it out on Regexr.com, doesn't work in NP++(?):
find: (?<=print)( ')(.*)(')
replace: ('$2')
for variables:
(?<=print)( )(.*)(\n)
('$2')\n
for label and variable:
(?<=print)( ')(.*)(',)(.*)(\n)
('$2',$4)\n
You can use operator oveloading:
class Print:
def __lt__(self, thing):
print(thing)
p = Print()
p < 'hello' # -> hello
Or if you like use << like in c++ iostreams.
You can't, because the only way you could do it without parentheses is having it be a keyword, like in Python 2. You can't manually define a keyword, so no.
In Python 3, print is a function, whereas it used to be a statement in previous versions. As #holdenweb suggested, use 2to3 to translate your code.
I have configured vim to auto-add the parens around my debug def calls when I write the file. I use a simple watcher that auto-runs my updates when the timestamp changes. And I defined CTRL+p to delete them all. The only caveat is that I have to have them alone on a line, which I pretty much always do. I thought about trying to save and restore my previous search-highlight. And I did find a solution on Stack. But it looked a little too deep for now. Now I can finally get back to debugging Ruby-style with a quick p<space><obj>.
function! PyAddParensToDebugs()
execute "normal! mZ"
execute "%s/^\\(\\s*\\)\\(p\\|pe\\|pm\\|pp\\|e\\|ppe\\)\\( \\(.*\\)\\)\\{-}$/\\1\\2(\\4)/"
execute "normal! `Z"
endfunction
autocmd BufWrite *.py silent! call PyAddParensToDebugs()
map <c-p> :g/^\\s*\\(p\\\|pe\\\|pm\\\|pp\\\|e\\\|ppe\\)\\( \\\|\(\\)/d<cr>
I use these Python defs to do my debug printing.
def e():
exit()
def pp(obj):
pprint.PrettyPrinter(indent=4).pprint(obj)
def ppe(obj):
pprint.PrettyPrinter(indent=4).pprint(obj)
exit()
def p(obj):
print(repr(obj))
def pe(obj):
print(repr(obj))
exit()
def pm():
print("xxx")
This is a bit of an odd question; it came up in the context of a tool that exposes a Python API, which we spend a lot of time querying interactively from the REPL. The particular idiom causing issues is something like this:
for var in slow_generator_of_giant_list():
stats = update(stats, var)
print stats
To enter this at the REPL, I can type this:
>>> for var in slow_generator_of_giant_list():
... stats = update(stats, var)
...
If I now attempt to type the print, I get a syntax error due to improper indentation. (Or else I put the print inside the loop and do it on every iteration.)
But if I hit enter to go to the next line, the loop runs immediately, and I have to wait for it to finish, or type the print command in the face of possible output coming at me, etc.
Obviously I can define a function containing the above, and it might be worth saving into a file anyway, but in the general case we're constructing these on the fly, and it would be nice to have a way to "schedule" a command to run after the end of a loop from the REPL. In a language with block delimiters, I could of course put it after the ending delimiter (and any necessary statement separator). But my coworkers and I were stumped trying to do something similar here.
Is there perhaps an ugly abuse of Pythonic syntax that will do the trick that my coworkers and I couldn't think of? Or a recommended way to avoid the problem while still making it easy to throw together ad hoc interactive queries?
Thanks for any pointers.
Not beautiful, but this should work:
>>> mygen = slow_generator_of_giant_list()
>>> try:
... while True: stats = update(stats, mygen.next())
... except StopIteration:
... print stats
...
I would just say that you would find it easier just to not use the interactive shell for this.
It's not much effort to save a file and run it. You only have to keep it around for as long as you use it.
I actually have found this answering on SO. I keep a file open in my text editor with a terminal in the right directory, and just use it as a scratchpad for mocking up answers in.
I find myself adding debugging "print" statements quite often -- stuff like this:
print("a_variable_name: %s" % a_variable_name)
How do you all do that? Am I being neurotic in trying to find a way to optimize this? I may be working on a function and put in a half-dozen or so of those lines, figure out why it's not working, and then cut them out again.
Have you developed an efficient way of doing that?
I'm coding Python in Emacs.
Sometimes a debugger is great, but sometimes using print statements is quicker, and easier to setup and use repeatedly.
This may only be suitable for debugging with CPython (since not all Pythons implement inspect.currentframe and inspect.getouterframes), but I find this useful for cutting down on typing:
In utils_debug.py:
import inspect
def pv(name):
record=inspect.getouterframes(inspect.currentframe())[1]
frame=record[0]
val=eval(name,frame.f_globals,frame.f_locals)
print('{0}: {1}'.format(name, val))
Then in your script.py:
from utils_debug import pv
With this setup, you can replace
print("a_variable_name: %s' % a_variable_name)
with
pv('a_variable_name')
Note that the argument to pv should be the string (variable name, or expression), not the value itself.
To remove these lines using Emacs, you could
C-x ( # start keyboard macro
C-s pv('
C-a
C-k # change this to M-; if you just want to comment out the pv call
C-x ) # end keyboard macro
Then you can call the macro once with C-x e
or a thousand times with C-u 1000 C-x e
Of course, you have to be careful that you do indeed want to remove all lines containing pv(' .
Don't do that. Use a decent debugger instead. The easiest way to do that is to use IPython and either to wait for an exception (the debugger will set off automatically), or to provoke one by running an illegal statement (e.g. 1/0) at the part of the code that you wish to inspect.
I came up with this:
Python string interpolation implementation
I'm just testing it and its proving handy for me while debugging.