Code to check a scripts activity (python) - python

Simple question:
Is there some code or function I can add into most scripts that would let me know its "running"?
So after you execute foo.py most people would see a blinking cursor. I currently am running a new large script and it seems to be working, but I wont know until either an error is thrown or it finish(might not finish).
I assume you could put a simple print "foo-bar"at the end of each for loop in the script?
Any other neat visual read out tricks?

I like clint.progress.bar. For logging, you can check Lggr.

The print "foo-bar" trick is basically what people do for quick&dirty scripts. However, if you have lots and lots of loops, you don't want to print a line for each one. Besides the fact that it'll fill the scrollback buffer of your terminal, on many terminals it's hard to see whether anything is happening when all it's doing is printing the same line over and over. And if your loops are quick enough, it may even mean you're spending more time printing than doing the actual work.
So, there are some common variations to this trick:
Print characters or short words instead of full lines.
Print something that's constantly changing.
Only print every N times through the loop.
To print a word without a newline, you just print 'foo',. To print a character with neither a newline nor a space, you have to sys.stdout.write('.'). Either way, people can see the cursor zooming along horizontally, so it's obvious how fast the feedback is.
If you're got a for n in … loop, you can print n. Or, if you're progressively building something, you can print len(something), or outfile.ftell(), or whatever. Even if it's not objectively meaningful, the fact that it's constantly changing means you can tell what's going on.
The easiest way to not print all the time is to add a counter, and do something like counter += 1; if counter % 250 == 0: print 'foo'. Variations on this include checking the time, and printing only if it's been, say, 1 or more seconds since the last print, or breaking the task into subtasks and printing at the end of each subtask.
And obviously you can mix and match these.
But don't put too much effort into it. If this is anything but a quick&dirty aid to your own use, you probably want something that looks more professional. As long as you can expect to be on a reasonably usable terminal, you can print a \r without a \n and overwrite the line repeatedly, allowing you to draw nice progress bars or other feedback (ala curl, wget, scp, and other similar Unix tools). But of course you also need to detect when you're not on a terminal, or at least write this stuff to stderr instead of stdout, so if someone redirects or pipes your script they don't get a bunch of garbage. And you might want to try to detect the terminal width, and if you can detect it and it's >80, you can scale the progress bar or show more information. And so on.
This gets complicated, so you probably want to look for a library that does it for you. There are a bunch of choices out there, so look through PyPI and/or the ActiveState recipes.

You could log things to a file. You could print out dots, like print ".".

Related

CLI cursor is overlapping the string printed to the console?

from time import sleep
for i in range(7200, -1 , -1):
print(f"{i}", end="\r")
sleep(1)
When I run the above python script, it counts down and replaces the old number with the current number so it all stays on the same line. However, per the below image, the CLI cursor (not sure if that's what it's called, I'm still fairly new to programming) overlaps the numbers. I'm not quite sure how to rectify this so the cursor doesn't do that. I'd prefer it to go to the next line, but if that isn't possible then go to the end of the printed number.
screenshot of issue
This happens both in VS Code and the mac terminal.
I wasn't able to find anything regarding this, but that's probably because I just don't know what terms to exactly use. I tried putting \r and \n in different places, but most of my attempts just kept printing to a new line.

Keeping the user's input intact when outputing to terminal at the same time

To simplify, let's say I'm trying to write a command line two-way chat in Python. I would like the user to input his message with input() at the command prompt, but a listening thread could print a message at any moment. By default, this would "break" the user's input. Visually something like this:
userB>Stop interuserA wrote:Hey check this out!
rupting me!
The closest I was able to find was this answer here which is almost, but not exactly, what I'm looking for, but it did point me towards the blessings package which seems to be what I need (although I'm happy with an answer for any package, or even pure ANSII).
What I'm trying to achieve is to print incoming output from a Thread above the user's input, so that his text doesn't break. Let's say the user is typing:
userB>Stop inter
Suddenly a message comes in from the thread, but our user's input doesn't brake:
userA says: Ok I won't interrupt you
userB>Stop inter
What should my threads theoretical print_incoming_message() method look like to achieve this?
NB: I'm using Linux and am not interested in cross-platform compatibility.
There are two ways of doing this.
One is to use ncurses. There are python bindings for this. With ncurses, the terminal screen is under your complete control, and you can print characters at any point.
Without ncurses, you can't write above the current line. What you can do, however, is print a \r character and go back to the beginning of the line.
If you save the user's input (say he wrote foo), and you want to print the line bar above that, you can output:
\rbar\nfoo
This will overwrite the current line, and introduce a newline, moving the user's input down. The effect is similar, but it won't be as tamper-proof as ncurses.

how do I keep my input at the same screen location?

My current input method is a for loop. I input an integer it gets added to a list then it goes around to the next input. This produces a new line each time it goes around. I would like to keep the input entries at the same location. I'm new to Python and programming in general so I have no clue where to start. My input statement is in this form:
var= input(" message: ")
Thank You
If you are working with UNIX or Windows terminals, you can add an ASCI escape ("\033[A") to move the cursor one line up to ask for input again, as shown in the example here, so in this way, you can get your input message at the same position by "overwriting" the previous input message.
tl;dr: there's a reason most simple applications don't do this: it's a lot of work for not very much payoff.
If you're talking about making sure that the "message: " line always appears in the same place in the window, then you can't do it with plain input: it doesn't take an "end of line" argument and actually the newline happens before input gets a hold of the input string. (I.e. when the user hits RETURN.)
You can do it, especially if you don't care about Windows, using getch mode, which basically says that the terminal passes characters to you, not whole lines, and you need to decide how to interpret them. The getch package seems like it might be able to help here, it even supports Windows!
Another option (probably not as effective or a nuclear bomb when what you need is a scalpel) would be to use something like curses or blessings' terminal.location abilities. And blessings, I believe, incorporates ANSI escape chars. (As mentioned in the other answer to this question, it's probably the right way to go.)

Python Console with Logging

I'm in the process of rewriting a server program, and I want to add into it a simple console input.
At the moment, it just serves data and prints out one or two lines for each thing it does, as a descriptive measure for anyone watching/debugging.
What I want is to have a "sticky" input bar that is always at the bottom, above which my debug prints appear, so that I can enter commands at any point while the program is printing. This would look a bit like:
...
[88.88.88.88] Handling Connection on Port 11452
[12.12.12.12] Received Data
[44.44.44.44] Sending Disconnect Sequence
>>>Enter Data Here at Any Time
Ideally, this would be done without curses as this would complicate matters. I feel like I must be missing a simple solution.
Thanks in Advance,
Freddy.
If you're looking for a slightly higher-level library than curses, there are a few, like urwid (although of course they don't come with Python, and have to be installed).
If you really want to avoid a windowing library, I suppose you could run the server under screen, configured with an input bar and a rest-of-the-window, and give the server the two virtual TTYs instead of normal input… but that would be a lot more work, not less.
If you want to go lower level, you can always use termios, search termcap, and manually write control sequences to manually take care of scrolling everything but the last line, moving the input cursor, and so on. But that's going to be even more work.
And of course there's always the super-hacky possibility: For every output, and after every input, "redraw" the whole screen by spamming a few hundred blank lines, re-writing the output, and writing the input line. This will look terrible, and not work in a variety of edge cases, but it does avoid any kind of windowing.
However, I think there's a much better way to solve this problem.
You've already got a server. Why not just serve the console API on another "control" port (maybe just on localhost) instead of on the stdin/stdout/tty? That will work even if the server is, e.g., running as a daemon. And it means you can use your favorite fancy Telnet or similar client as a console, instead of having to write something from scratch.

Subsequent "list" commands in ipdb

I just noticed an odd behavior when using l (i.e. the list command) in ipdb. I think I have seen something similar with the Perl debugger in the past, but it still puzzles me.
The first time I inoke it shows corerectly ~10 lines of code around the current step (breakpoint). However, if I press it repeatedly, it does not show code around the current location anymore, but instead it shows code that comes below it.
Eventually list shows the final lines of the script, and if I press l again it doesn't show anything anymore.
Why is this, and how can I have it behave consistently as the first time I invoke it?
Many command line debuggers behave that way. (pdb, gdb, ipdb ...).
If you want display current line again, specify the line number.
l 42
If you don't know the current line number, issue where command.
The reason several list commands in most debuggers show different lines is for the simple reason that it doesn't make a lot of sense to show the same source code lines over and over. Presumably you can scroll back to see what you saw before.
That said, let me say that if you are willing to use the trepan debugger, it does have the ability to show the same source code lines for where you are currently stopped using "list .". To see lines before the last list, use "list -".
You can also set how many lines you want to list by default using "set listsize".
This command in pdb always shows the source text around the debugger's current line
(pdb) l .

Categories

Resources