Apakah ada cara dalam python untuk menentukan lebar konsol secara terprogram? Maksud saya jumlah karakter yang cocok dalam satu baris tanpa pembungkus, bukan lebar piksel jendela.
Edit
Mencari solusi yang berfungsi di Linux
Apakah ada cara dalam python untuk menentukan lebar konsol secara terprogram? Maksud saya jumlah karakter yang cocok dalam satu baris tanpa pembungkus, bukan lebar piksel jendela.
Edit
Mencari solusi yang berfungsi di Linux
Jawaban:
import os
rows, columns = os.popen('stty size', 'r').read().split()
menggunakan perintah 'stty size' yang menurut utas pada milis python cukup universal di linux. Ini membuka perintah 'stty size' sebagai file, 'membaca' dari itu, dan menggunakan split string sederhana untuk memisahkan koordinat.
Tidak seperti nilai os.environ ["COLUMNS"] (yang saya tidak dapat mengakses meskipun menggunakan bash sebagai shell standar saya), data juga akan diperbarui sedangkan saya percaya os.environment ["COLUMNS"] nilai hanya akan valid untuk waktu peluncuran interpreter python (misalkan pengguna mengubah ukuran jendela sejak itu).
(Lihat jawaban oleh @GringoSuave tentang cara melakukan ini di python 3.3+)
rows, columns = subprocess.check_output(['stty', 'size']).split()
sedikit lebih pendek, ditambah subproses adalah masa depan
rows, columns = subprocess.check_output(['stty', 'size']).decode().split()
Jika Anda ingin string unicode untuk kompatibilitas py2 / 3
Tidak yakin mengapa itu ada dalam modul shutil
, tetapi ia mendarat di Python 3.3, menanyakan ukuran terminal keluaran :
>>> import shutil
>>> shutil.get_terminal_size((80, 20)) # pass fallback
os.terminal_size(columns=87, lines=23) # returns a named-tuple
Implementasi tingkat rendah ada di modul os. Juga berfungsi di Windows.
Backport sekarang tersedia untuk Python 3.2 dan di bawah:
python3.5
diinstal.
Inappropriate ioctl for device
error / peringatan, atau mendapatkan nilai fallback yang didefinisikan sebesar 80.
menggunakan
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
EDIT : oh, maafkan saya. Itu bukan standar python lib, inilah sumber console.py (saya tidak tahu dari mana asalnya).
Modul ini tampaknya bekerja seperti itu: Ini memeriksa jika termcap
tersedia, ketika ya. Itu menggunakannya; jika tidak memeriksa apakah terminal mendukung ioctl
panggilan khusus dan itu tidak berfungsi juga, ia memeriksa variabel lingkungan yang diekspor oleh beberapa shell. Ini mungkin hanya akan bekerja pada UNIX.
def getTerminalSize():
import os
env = os.environ
def ioctl_GWINSZ(fd):
try:
import fcntl, termios, struct, os
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
'1234'))
except:
return
return cr
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
### Use get(key[, default]) instead of a try/catch
#try:
# cr = (env['LINES'], env['COLUMNS'])
#except:
# cr = (25, 80)
return int(cr[1]), int(cr[0])
Kode di atas tidak mengembalikan hasil yang benar di linux saya karena winsize-struct memiliki 4 celana pendek yang tidak ditandatangani, bukan 2 celana pendek yang ditandatangani:
def terminal_size():
import fcntl, termios, struct
h, w, hp, wp = struct.unpack('HHHH',
fcntl.ioctl(0, termios.TIOCGWINSZ,
struct.pack('HHHH', 0, 0, 0, 0)))
return w, h
hp dan hp harus mengandung lebar dan tinggi piksel, tetapi tidak.
fcntl.ioctl(sys.stdin.fileno(), ...
stdout
atau stderr
bukannya stdin
. stdin
mungkin pipa. Anda mungkin juga ingin menambahkan baris seperti if not os.isatty(0): return float("inf")
.
Saya mencari-cari dan menemukan solusi untuk windows di:
http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/
dan solusi untuk linux di sini.
Jadi di sini adalah versi yang berfungsi baik di linux, os x dan windows / cygwin:
""" getTerminalSize()
- get width and height of console
- works on linux,os x,windows,cygwin(windows)
"""
__all__=['getTerminalSize']
def getTerminalSize():
import platform
current_os = platform.system()
tuple_xy=None
if current_os == 'Windows':
tuple_xy = _getTerminalSize_windows()
if tuple_xy is None:
tuple_xy = _getTerminalSize_tput()
# needed for window's python in cygwin's xterm!
if current_os == 'Linux' or current_os == 'Darwin' or current_os.startswith('CYGWIN'):
tuple_xy = _getTerminalSize_linux()
if tuple_xy is None:
print "default"
tuple_xy = (80, 25) # default value
return tuple_xy
def _getTerminalSize_windows():
res=None
try:
from ctypes import windll, create_string_buffer
# stdin handle is -10
# stdout handle is -11
# stderr handle is -12
h = windll.kernel32.GetStdHandle(-12)
csbi = create_string_buffer(22)
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
except:
return None
if res:
import struct
(bufx, bufy, curx, cury, wattr,
left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
sizex = right - left + 1
sizey = bottom - top + 1
return sizex, sizey
else:
return None
def _getTerminalSize_tput():
# get terminal width
# src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window
try:
import subprocess
proc=subprocess.Popen(["tput", "cols"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
output=proc.communicate(input=None)
cols=int(output[0])
proc=subprocess.Popen(["tput", "lines"],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
output=proc.communicate(input=None)
rows=int(output[0])
return (cols,rows)
except:
return None
def _getTerminalSize_linux():
def ioctl_GWINSZ(fd):
try:
import fcntl, termios, struct, os
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,'1234'))
except:
return None
return cr
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
try:
cr = (env['LINES'], env['COLUMNS'])
except:
return None
return int(cr[1]), int(cr[0])
if __name__ == "__main__":
sizex,sizey=getTerminalSize()
print 'width =',sizex,'height =',sizey
Itu baik:
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
The shutil
Fungsi hanya bungkus sekitar os
satu yang menangkap beberapa kesalahan dan mengatur fallback, namun memiliki satu peringatan besar - rusak ketika pipa! , yang merupakan kesepakatan yang cukup besar.
Untuk mendapatkan ukuran terminal saat menggunakan pipa os.get_terminal_size(0)
sebagai gantinya.
Argumen pertama 0
adalah argumen yang menunjukkan bahwa deskriptor file stdin harus digunakan daripada stdout default. Kami ingin menggunakan stdin karena stdout melepaskan sendiri ketika sedang dipipihkan yang dalam hal ini menimbulkan kesalahan.
Saya sudah mencoba mencari tahu kapan masuk akal untuk menggunakan stdout daripada argumen stdin dan tidak tahu mengapa itu default di sini.
os.get_terminal_size()
diperkenalkan dalam Python 3.3
os.get_terminal_size(0)
akan macet jika Anda pipa ke stdin. Coba:echo x | python3 -c 'import os; print(os.get_terminal_size(0))'
Mulai dari Python 3.3 dengan langsung: https://docs.python.org/3/library/os.html#querying-the-size-of-a-terminal
>>> import os
>>> ts = os.get_terminal_size()
>>> ts.lines
24
>>> ts.columns
80
shutil.get_terminal_size() is the high-level function which should normally be used, os.get_terminal_size is the low-level implementation.
Sepertinya ada beberapa masalah dengan kode itu, Johannes:
getTerminalSize
perlu import os
env
? Sepertinya os.environ
.Juga, mengapa beralih lines
dan cols
sebelum kembali? Jika TIOCGWINSZ
dan stty
keduanya mengatakan lines
itu cols
, saya katakan biarkan seperti itu. Ini membingungkan saya selama 10 menit sebelum saya melihat ketidakkonsistenan.
Sridhar, saya tidak mendapatkan kesalahan itu ketika saya menyalurkan output. Saya cukup yakin itu tertangkap dengan baik di coba-kecuali.
pascal, "HHHH"
tidak berfungsi pada mesin saya, tetapi "hh"
tidak. Saya kesulitan menemukan dokumentasi untuk fungsi itu. Sepertinya itu tergantung platform.
chochem, berbadan hukum.
Ini versi saya:
def getTerminalSize():
"""
returns (lines:int, cols:int)
"""
import os, struct
def ioctl_GWINSZ(fd):
import fcntl, termios
return struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))
# try stdin, stdout, stderr
for fd in (0, 1, 2):
try:
return ioctl_GWINSZ(fd)
except:
pass
# try os.ctermid()
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
try:
return ioctl_GWINSZ(fd)
finally:
os.close(fd)
except:
pass
# try `stty size`
try:
return tuple(int(x) for x in os.popen("stty size", "r").read().split())
except:
pass
# try environment variables
try:
return tuple(int(os.getenv(var)) for var in ("LINES", "COLUMNS"))
except:
pass
# i give up. return default.
return (25, 80)
Banyak implementasi Python 2 di sini akan gagal jika tidak ada terminal pengendali saat Anda memanggil skrip ini. Anda dapat memeriksa sys.stdout.isatty () untuk menentukan apakah ini sebenarnya terminal, tetapi itu akan mengecualikan banyak kasus, jadi saya percaya cara paling pythonic untuk mengetahui ukuran terminal adalah dengan menggunakan paket kutukan bawaan.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
Saya sedang mencoba solusi dari sini yang memanggil ke stty size
:
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
Namun ini gagal bagi saya karena saya sedang mengerjakan skrip yang mengharapkan input diarahkan pada stdin, dan stty
akan mengeluh bahwa "stdin bukan terminal" dalam kasus itu.
Saya dapat membuatnya bekerja seperti ini:
with open('/dev/tty') as tty:
height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
Coba "berkah"
Saya mencari hal yang sama. Sangat mudah digunakan dan menawarkan alat untuk mewarnai, menata dan memposisikan di terminal. Yang Anda butuhkan semudah:
from blessings import Terminal
t = Terminal()
w = t.width
h = t.height
Bekerja seperti pesona di Linux. (Saya tidak yakin tentang MacOSX dan Windows)
Unduh dan dokumentasi di sini
atau Anda dapat menginstalnya dengan pip:
pip install blessings
@ reannual's jawaban berfungsi dengan baik, tetapi ada masalah dengan itu: os.popen
sekarang sudah usang . The subprocess
Modul harus digunakan sebagai gantinya, jadi di sini adalah versi kode @ reannual yang menggunakan subprocess
dan langsung menjawab pertanyaan (dengan memberikan lebar kolom secara langsung sebagai int
:
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
Diuji pada OS X 10.9
Jika Anda menggunakan Python 3.3 atau lebih tinggi, saya akan merekomendasikan built-in get_terminal_size()
seperti yang telah direkomendasikan. Namun jika Anda terjebak dengan versi yang lebih lama dan menginginkan cara yang sederhana dan lintas platform untuk melakukan ini, Anda dapat menggunakan asciimatics . Paket ini mendukung versi Python kembali ke 2.7 dan menggunakan opsi serupa dengan yang disarankan di atas untuk mendapatkan ukuran terminal / konsol saat ini.
Cukup buat Screen
kelas Anda dan gunakan dimensions
properti untuk mendapatkan tinggi dan lebar. Ini telah terbukti berfungsi di Linux, OSX dan Windows.
Oh - dan pengungkapan penuh di sini: Saya adalah penulis, jadi silakan membuka masalah baru jika Anda memiliki masalah dalam menjalankannya.
Ini adalah versi yang seharusnya kompatibel dengan Linux dan Solaris. Berdasarkan posting dan komitmen dari madchine . Membutuhkan modul subproses.
def termsize (): impor shlex, subproses, ulang output = subprocess.check_output (shlex.split ('/ bin / stty -a')) m = penelitian ulang ('rows \ D + (? P \ d +); kolom \ D + (? P \ d +);', output) jika m: return m.group ('rows'), m.group ('kolom') meningkatkan OSError ('Respons buruk:% s'% (output))
>>> termsize () ('40', '100')