I couldn't find anything with a quick Google search, nor anything on here, saving for this. However, it doesn't do the trick. So how exactly do you resize the terminal using Python?
To change the tty/pty setting you have to use an ioctl on the stdin file descriptor.
import termios
import struct
import fcntl
def set_winsize(fd, row, col, xpix=0, ypix=0):
winsize = struct.pack("HHHH", row, col, xpix, ypix)
fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize)
But to change the actual window size you can use terminal escape sequences, but not all terminals support or enable that feature. If you're using urxvt you can do this:
import sys
sys.stdout.write("\x1b[8;{rows};{cols}t".format(rows=32, cols=100))
But that may not work on all terminals.
If you install xdotool, you can change the size of the terminal window with something like this:
import subprocess
import shlex
id_cmd='xdotool getactivewindow'
resize_cmd='xdotool windowsize --usehints {id} 100 30'
proc=subprocess.Popen(shlex.split(id_cmd),stdout=subprocess.PIPE)
windowid,err=proc.communicate()
proc=subprocess.Popen(shlex.split(resize_cmd.format(id=windowid)))
proc.communicate()
PS. On Ubuntu xdotool is provided by a package of the same name.
Related
Is it possible to make a python script that will delete the .py file at the end of its execution (self-delete) in windows?
This way makes your program non OS dependant.
from os import remove
from sys import argv
remove(argv[0])
Bonus points:
When parsing arguments the very first argument that you get in sys.argv is equals to "path-to-filename/filename.py"
Neomind's answer seems to do the trick. But if deleting the file while it's in memory bothers you, and you're looking for a pure python solution, then you could use subprocess to create a new process with the explicit purpose of deleting your original script file. Something like this should work:
import sys, subprocess
subprocess.Popen("python -c \"import os, time; time.sleep(1); os.remove('{}');\"".format(sys.argv[0]))
sys.exit(0)
You probably wouldn't need the timeout in there but I've added it just to make sure that the process from the original script has been given enough time to close itself.
I'm not sure deleting a file while it's in memory would be a good idea. Try running a batch file from the script which closes the script process, then deletes the script file.
There may be a native method to self destruct a script, but I am not aware of it.
EDIT: Here is a simple example of how you could accomplish this using the method I described:
In the script
# C:\test.py
import os
os.startfile(r"C:\sampleBatch.bat")
In the batch
# C:\sampleBatch.bat
TASKKILL /IM "process name" #For me, this was "ipy64.exe" because I use IronPython.
DEL "C:\test.py"
You may not even need to kill the process to delete the file, but it is safer to do so. Hope this helps.
Yes, you could use the following:
import os
import sys
import subprocess
# execute and remove after run
(Your python code)
# end of file
dir = os.getcwd()
os.remove(dir+'\%s' % sys.argv[0])
This script can be modified of course, but besides that this should work
You could also make use of the atexit module.
import os, atexit
atexit.register(lambda file = __file__: os.remove(file))
There is a rather simple method:
import os
os.remove("insert the file's path")
If you're facing problems, place an 'r' before the starting quotations mark.
Wrapper should handle special control characters and do something but otherwise not interfere with the actual application. (trying to build a tmux like app)
So far I have the below modifying example in doc: https://docs.python.org/3/library/pty.html#example
import pty
import os
def handle_special_cmd(data):
# TODO
raise NotImplementedError
def inread(fd):
data = os.read(fd, 1024)
if b'\x02' in data: # ctrl B
return handle_special_cmd(data)
return data
def main():
cmd="vim"
pty.spawn(cmd, stdin_read=inread)
if __name__=='__main__':
main()
The above code works but the vim opened does not cover the entire terminal window. It starts vim with reduced rows and columns
If I just type vim from the shell it works fine:
Why does this occur and how to fix it? My goal is not just fix the rows and columns but the wrapper should be truely transparent except trap the special ctrl character and do some stuff. whatever tty / colors and other settings the current shell has should be passed on to the actual executable. It should work as if I typed vim. (Linux specific solution is fine. Need not work in all posix. If it needs a c extension is also fine).
The window size is, uniquely, a property of the PTY itself. You can get and set it using the TIOCGWINSZ and TIOCSWINSZ ioctls:
import sys, fcntl, termios, struct
buf = bytearray(4)
fcntl.ioctl(sys.stdin.fileno(), termios.TIOCGWINSZ, buf)
(h, w) = struct.unpack("HH", buf)
print("Terminal is {w} x {h}".format(w=w, h=h))
[...]
fcntl.ioctl(child_pty.fileno(), termios.TIOCSWINSZ, struct.pack("HH", h, w))
I am using PIL to open a single image in the default image viewer:
from PIL import Image
img = Image.open('example.jpg')
img.show()
Does any Python module contain a function enabling opening multiple images in the current system's default image viewer? For instance when on OS X, Preview.app should open with the list of images in the sidebar. From the command line this is no problem at all:
$ open my_picture_number_*
Use case is that users should just be able to explore a few dozen images.
Use subprocess.run to run the operating system's default image viewing app. subprocess.run works a lot like a command line. You just need to know what the command is for the operating system you're on. For windows, "explorer" will do; for OS X, as you point out, it's "open." I'm not sure what it is for Linux, maybe "eog"?
So, your code would look like this:
import sys
import subprocess
def openImage(path):
imageViewerFromCommandLine = {'linux':'xdg-open',
'win32':'explorer',
'darwin':'open'}[sys.platform]
subprocess.run([imageViewerFromCommandLine, path])
I've tried to use #jgfoot's answer, which worked, but made my program hang after the viewer was launched. I've solved this issue by using subprocess.Popen instead, like this:
import sys
import subprocess
def openImage(path):
imageViewerFromCommandLine = {'linux':'xdg-open',
'win32':'explorer',
'darwin':'open'}[sys.platform]
subprocess.Popen([imageViewerFromCommandLine, path])
If I run this in python under linux it works:
start = "\033[1;31m"
end = "\033[0;0m"
print "File is: " + start + "<placeholder>" + end
But if I run it in Windows it doesn't work, how can I make the ANSI escape codes work also on Windows?
For windows, calling os.system("") makes the ANSI escape sequence get processed correctly:
import os
os.system("") # enables ansi escape characters in terminal
COLOR = {
"HEADER": "\033[95m",
"BLUE": "\033[94m",
"GREEN": "\033[92m",
"RED": "\033[91m",
"ENDC": "\033[0m",
}
print(COLOR["GREEN"], "Testing Green!!", COLOR["ENDC"])
Here is the solution I have long sought. Simply use the ctypes module, from the standard library. It is installed by default with Python 3.x, only on Windows. So check if the OS is Windows before to use it (with platform.system, for example).
import os
if os.name == 'nt': # Only if we are running on Windows
from ctypes import windll
k = windll.kernel32
k.SetConsoleMode(k.GetStdHandle(-11), 7)
After you have done that, you can use ASCII special characters (like \x1b[31m, for red color) as if you were on a Unix operating system :
message = "ERROR"
print(f"\x1b[31m{message}\x1b[0m")
I like this solution because it does not need to install a module (like colorama or termcolor).
You could check Python module to enable ANSI colors for stdout on Windows? to see if it's useful.
The colorama module seems to be cross-platform.
You install colorama:
pip install colorama
Then:
import colorama
colorama.init()
start = "\033[1;31m"
end = "\033[0;0m"
print "File is: " + start + "<placeholder>" + end
If you are on Win 10 (with native ANSI support in cmd) there seems to be a bug which was marked as resolved in Python 3.7 (though it doesn't look it was actually fixed).
One workaround is to add subprocess.call('', shell=True) before printing.
You could take a look at https://github.com/kennethreitz/clint
From the readme:
>>> from clint.textui import colored, puts
>>> puts(colored.red('red text'))
red text
# It's red in Windows, OSX, and Linux alike.
You can just do this:
import os
os.system("")
This works for me. Command prompt does support color by default.
Sending the ANSI escape sequences should work, according to thousands of fine answers on the internet, but one obscure detail took me two half days to stumble upon. The trick is that a certain registry key must be set. I'm using (just for today) Windows 10 Enterprise, version 1709, build 16299.
In HKEY_CURRENT_USER, under Console, right between TrimLeadingZeros and WindowAlpha there should be VirtualTerminalLevel. If it doesn't exist, go ahead and create it. It's a REG_DWORD. Set its value to 1. Open a new terminal, run Python, and have a bit o' fun.
print("\033[48;2;255;140;60m ORANGE BACKGROUND \033[48;2;0;0;0m")
See https://github.com/ytdl-org/youtube-dl/issues/15758 to read stuff by people who know more than I do about this.
Now if I could remember why I wanted to colorize my Python program's output...
Here is a bit simpler code I have used.
import os
os.system("color") # Alternative - os.system("")
TCOLOR = "\033[31;3m"
ENDC = "\033[m"
print (TCOLOR + "Make yourself happy" + ENDC)
I wrote a simple module, available at: http://pypi.python.org/pypi/colorconsole
It works with Windows, Mac OS X and Linux. It uses ANSI for Linux and Mac, but native calls to console functions on Windows. You have colors, cursor positioning and keyboard input. It is not a replacement for curses, but can be very useful if you need to use in simple scripts or ASCII games.
The docs can be found here: http://code.google.com/p/colorconsole/wiki/PageName
PS: This is the same answer for Print in terminal with colors using Python?, but I didn't know how to link to a reply.
Try adding a semi-colon here \033[;, I get undesirable effects without that semi-colon.
start = "\033[;1;31m"
end = "\033[;0;0m"
import os
os.system("")
COR = {
"HEADER": "\033[95m",
"BLUE": "\033[94m",
"GREEN": "\033[92m",
"RED": "\033[91m",
"ENDC": "\033[0m",
}
print(COR["RED"]+"Testing Green!!"+COR["ENDC"])
Is it possible to make a python script that will delete the .py file at the end of its execution (self-delete) in windows?
This way makes your program non OS dependant.
from os import remove
from sys import argv
remove(argv[0])
Bonus points:
When parsing arguments the very first argument that you get in sys.argv is equals to "path-to-filename/filename.py"
Neomind's answer seems to do the trick. But if deleting the file while it's in memory bothers you, and you're looking for a pure python solution, then you could use subprocess to create a new process with the explicit purpose of deleting your original script file. Something like this should work:
import sys, subprocess
subprocess.Popen("python -c \"import os, time; time.sleep(1); os.remove('{}');\"".format(sys.argv[0]))
sys.exit(0)
You probably wouldn't need the timeout in there but I've added it just to make sure that the process from the original script has been given enough time to close itself.
I'm not sure deleting a file while it's in memory would be a good idea. Try running a batch file from the script which closes the script process, then deletes the script file.
There may be a native method to self destruct a script, but I am not aware of it.
EDIT: Here is a simple example of how you could accomplish this using the method I described:
In the script
# C:\test.py
import os
os.startfile(r"C:\sampleBatch.bat")
In the batch
# C:\sampleBatch.bat
TASKKILL /IM "process name" #For me, this was "ipy64.exe" because I use IronPython.
DEL "C:\test.py"
You may not even need to kill the process to delete the file, but it is safer to do so. Hope this helps.
Yes, you could use the following:
import os
import sys
import subprocess
# execute and remove after run
(Your python code)
# end of file
dir = os.getcwd()
os.remove(dir+'\%s' % sys.argv[0])
This script can be modified of course, but besides that this should work
You could also make use of the atexit module.
import os, atexit
atexit.register(lambda file = __file__: os.remove(file))
There is a rather simple method:
import os
os.remove("insert the file's path")
If you're facing problems, place an 'r' before the starting quotations mark.