Python - Clearing the terminal screen more elegantly - python

I know you can clear the shell by executing clear using os.system, but this way seems quite messy to me since the commands are logged in the history and are litterally interpreted as commands run as the user to the OS.
I'd like to know if there is a better way to clear the output in a commandline script?

print "\033c"
works on my system.
You could also cache the clear-screen escape sequence produced by clear command:
import subprocess
clear_screen_seq = subprocess.check_output('clear')
then
print clear_screen_seq
any time you want to clear the screen.
tput clear command that produces the same sequence is defined in POSIX.
You could use curses, to get the sequence:
import curses
import sys
clear_screen_seq = b''
if sys.stdout.isatty():
curses.setupterm()
clear_screen_seq = curses.tigetstr('clear')
The advantage is that you don't need to call curses.initscr() that is required to get a window object which has .erase(), .clear() methods.
To use the same source on both Python 2 and 3, you could use os.write() function:
import os
os.write(sys.stdout.fileno(), clear_screen_seq)
clear command on my system also tries to clear the scrollback buffer using tigetstr("E3").
Here's a complete Python port of the clear.c command:
#!/usr/bin/env python
"""Clear screen in the terminal."""
import curses
import os
import sys
curses.setupterm()
e3 = curses.tigetstr('E3') or b''
clear_screen_seq = curses.tigetstr('clear') or b''
os.write(sys.stdout.fileno(), e3 + clear_screen_seq)

You can use the Python interface to ncurses, specifically window.erase and window.clear.
https://docs.python.org/3.5/library/curses.html

I use 2 print statements to clear the screen.
Clears the screen:
print(chr(27) + "[2J")
Moves cursor to begining row 1 column 1:
print(chr(27) + "[1;1f")
I like this method because you can move the cursor anywhere you want by [<row>;<col>f
The chr(27) is the escape character and the stuff in quotes tells the terminal what to do.

Related

How to write to an other terminal with a running program in it in Python 2.7?

I am currently making a program in python to open minecraft servers. I've already done a window where you can choose a server in a list and launch it or make a backup. When you launch it, a new terminal open (with os.system('gnome-terminal...')) and the java program starts. Is there a way to send some text (like commands) to this java program from the first terminal ?
Here is my code
I've tried many things with subprocess but without a satisfying result.
EDIT:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import gtk
import re
import os
import time
active_button = 0
servers = [["Server 1","/home/myname/Desktop/server1","server.jar"],
["Serveur 2","/home/myname/Desktop/server2","server.jar"]]
def button_selection(button, num):
global active_button
state=button.state
if state >= 1:
active_button = int(num)
def validation(widget):
path = servers[active_button][1]
server = servers[active_button][2]
command = """gnome-terminal --working-directory="%s" -e 'java -jar %s'""" % (path, server)
print(command)
os.system(command)
def save(widget):
path = servers[active_button][1]
server = servers[active_button][2]
print "cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T"))
os.system("cp -a '%s' /home/myname/Documents/backups_minecraft_servers/%s" % (path+"/world", time.strftime("%d_%m_%Y-%T")))
print("Backup finished")
def main():
window = gtk.Window()
vbox = gtk.VBox()
hbox = gtk.HBox()
validate = gtk.Button("Validate")
validate.connect("clicked", validation)
backup = gtk.Button("Backup")
backup.connect("clicked", save)
hbox.pack_start(validate)
hbox.pack_start(vbox)
hbox.pack_start(backup)
buttons = [gtk.RadioButton(None, servers[0][0])]
vbox.pack_start(buttons[0])
for server in servers[1:]:
buttons.append(gtk.RadioButton(buttons[0], server[0]))
vbox.pack_start(buttons[-1])
for i in range(len(buttons)):
buttons[i].connect("toggled", button_selection, i)
window.add(hbox)
window.show_all()
gtk.main()
if __name__=="__main__":
main()
First off, don't ever use os.system. Always use the subprocess module for launching new processes, as it handles many of the edge cases much better. subprocess.check_call can do everything os.system can do, and much more, and it checks for errors, something os.system doesn't do.
Secondly, don't use gnome-terminal to create an interactive terminal to run your subprocess in! Create a pseudoterminal (pty) instead; that way your program can maintain control over the behavior of the child. Underneath the hood, that's how a program like gnome-terminal works itself: it creates a pty for the shell and the programs launched by the shell to run in, and then it reads from the pty and renders the results graphically.
Your program can create a pty for each child program you want to run, and then your program can communicate with the child program exactly like how gnome-terminal can. You can do this with the pty module in the Python standard library, but you might want to consider using the pexpect package instead as it simplifies the process substantially.
If you don't need a full terminal, you can do this even more simply by just opening a pipe to the child process. The subprocess module in the standard library provides the Popen class which can be used to do this.
In your specific case I would recommend pexpect. It's easy to use and will "do the right thing" for this kind of job.

grab serial input line and move them to a shell script

I tries to grab a uart - line and give this string to a shell script;
#!/usr/bin/env python
import os
import serial
ser = serial.Serial('/dev/ttyAMA0', 4800)
while True :
try:
state=ser.readline()
print(state)
except:
pass
So, "state" should given to a shell script now,
like: myscript.sh "This is the serial input..."
but how can I do this?
print(os.system('myscript.sh ').ser.readline())
doesn't work.
Just simple string concatenation passed to the os.system function.
import os
os.system("myscript.sh " + ser.readline())
If myscript can continuously read additional input, you have a much more efficient pipeline.
from subprocess import Popen, PIPE
sink = Popen(['myscript.sh'], stdin=PIPE, stdout=PIPE)
while True:
sink.communicate(ser.readline())
If you have to start a new myscript.sh for every input line, (you'll really want to rethink your design, but) you can, of course:
while True:
subprocess.check_call(['myscript.sh', ser.readline())
Notice how in both cases we avoid a pesky shell.
There are different ways to combine two strings (namely "./myscript.sh" and ser.readLine()), which will then give you the full command to be run by use of os.system. E.g. strings can be arguments of the string.format method:
os.system('myscript.sh {}'.format(ser.readline()))
Also you can just add two strings:
os.system('myscript.sh '+ser.readline())
I am not sure what you want to achieve with the print statement. A better way to handle the call and input/output of your code would be to switch from os to the subprocess module.

How to replace text on a screen after delay?

I am very new to Python and I would like to know how I would clear a text that has been printed and add another piece of text. For example, I would like to display "Hello" then program with a delay of 10 seconds to replace text with another text "Goodbye". I am using Python 3.3 on Windows 7.
import time
import os
print ('hello there')
time.sleep(10) # this will BLOCK your program for 10 seconds
os.system('cls') # clear the screen, since cls is the clear screen command for windows
print ('bye')
input() # this is to wait to user to enter something to exist
version 2, using some 'visual' effects :D
import time
import os
print ('hello there')
for i in range(1, 10):
time.sleep(1)
print ('.')
os.system('cls')
print ('bye')
input()
Once text is sent to stdout, there really isn't a good way to change it. What you probably want to do would require a UI library such as tkinter (which comes with Python) or wxPython. Then you can create a Window with a label widget that can change every few seconds. You might be able to use Python's curses library too, but I have yet to see a coherent tutorial on how you would use that for this sort of thing.
Python's output is based on an abstraction of "output is just a file that you can write to", so there's no way to do this cross-platform.
However, if you want it to work in a Windows cmd.exe console (aka "DOS prompt"), and don't care about working inside IDLE, on Unix, over a network, etc., you can use the MSVCRT console I/O APIs.
Unfortunately, the limited set of console I/O APIs built into the standard library doesn't include the clear function. But you can look for third-party extended console I/O libraries on PyPI, or use PyWin32 to call the MSVCRT functions directly.
Or you can use a cheap hack:
import subprocess
subprocess.check_call(['cls'])
This just calls the cls function, which does everything for you.

How to run and control a commandline program from python?

I have a python script which will give an output file. I need to feed this output file to a command line program. Is there any way I could call the commandline program and control it to process the file in python?
I tried to run this code
import os
import subprocess
import sys
proc = subprocess.Popen(["program.exe"], stdin=subprocess.PIPE)
proc.communicate(input=sys.argv[1]) #here the filename should be entered
proc.communicate(input=sys.argv[2]) #choice 1
proc.communicate(input=sys.argv[3]) #choice 2
is there any way I could enter the input coming from the commandline. And also though the cmd program opens the interface flickers after i run the code.
Thanks.
Note: platform is windows
Have a look at http://docs.python.org/library/subprocess.html. It's the current way to go when starting external programms. There are many examples and you have to check yourself which one fits your needs best.
You could do os.system(somestr) which lets you execute semestr as a command on the command line. However, this has been scrutinized over time for being insecure, etc (will post a link as soon as I find it).
As a result, it has been conventionally replaced with subprocess.popen
Hope this helps
depending on how much control you need, you might find it easier to use pexpect which makes parsing the output of the program rather easy and can also easily be used to talk to the programs stdin. Check out the website, they have some nice examples.
If your target program is expecting the input on STDIN, you can redirect using pipe:
python myfile.py | someprogram
As I just answered another question regarding subprocess, there is a better alternative!
Please have a look at the great library python sh, it is a full-fledged subprocess interface for Python that allows you to call any program as if it were a function, and more important, it's pleasingly pythonic.
Beside redirecting data stream with pipes, you can also process a command line such as:
mycode.py -o outputfile inputfilename.txt
You must import sys
import sys
and in you main function:
ii=1
infile=None
outfile=None
# let's process the command line
while ii < len(sys.argv):
arg = sys.argv[ii]
if arg == '-o':
ii = ii +1
outfile = sys.argv[ii]
else:
infile=arg
ii = ii +1
Of course, you can add some file checking, etc...

Display temporary message in terminal that is not stored in terminal history

I would like to create a command line password file decryption script that would reveal the contents of an encrypted file in a terminal window for a maximum of say 10 seconds, after which point the text is automatically cleared.
I'm not really sure what the correct terminology for this sort of functionality would be, so sorry if the answer is available via the correct search string.
If you only need to display one line of "secret" output, you could use "carriage return" and overwrite the line. It does not leave any traces in the terminal history.
from __future__ import print_function
import time
import sys
print("hello", end = '')
sys.stdout.flush()
time.sleep(1)
print("\rxxxxx")
sys.stdout.flush()
You can clear the terminal with ansi escape sequences. This works on almost every terminal emulator (except the win32 console).
import time
import sys
print '\x1b[0;0H\x1b[2J' # home cursor, clear screen
print 'terribly secret file contents'
time.sleep(2)
print '\x1b[2J'
sys.stdout.flush() # flush output buffer.
However, if the output of your program is redirected to a file it will be captured nonetheless.
Additionally, you might have to disable the terminal's scrollback buffer.

Categories

Resources