Cara mendapatkan lebar jendela konsol Linux dengan Python
264
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.
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+)
Anda bisa membuat ini berfungsi pada Solaris juga jika alih-alih "ukuran" Anda lulus "-a". Akan ada "rows = Y; kolom = X" di output dipisahkan titik koma.
Joseph Garvin
5
COLUMNS tidak diekspor secara default di Bash, itu sebabnya os.environ ["COLUMNS"] tidak berfungsi.
Kjell Andreassen
38
rows, columns = subprocess.check_output(['stty', 'size']).split()sedikit lebih pendek, ditambah subproses adalah masa depan
cdosborn
7
tput lebih baik daripada stty, karena stty tidak dapat bekerja dengan PIPE.
liuyang1
5
rows, columns = subprocess.check_output(['stty', 'size']).decode().split()Jika Anda ingin string unicode untuk kompatibilitas py2 / 3
Itu karena Anda seharusnya tidak menggunakan 2.7 lagi, lakukan lompatan ke 3.x itu sangat berharga.
anthonyryan1
5
@osirisgothra Banyak penyedia hosting belum mendukung python3, jadi sebagian dari kita terpaksa menggunakan python2 untuk pengembangan back end. Meskipun itu seharusnya tidak ada hubungannya dengan mendapatkan ukuran terminal ...
whitebeard
4
@osirisgothra Karena ada banyak kode Python 2 yang akan membutuhkan terlalu banyak pekerjaan untuk port. Juga, Pypy masih memiliki dukungan Python 3 yang agak buruk.
Antimony
2
@whitebeard Apakah ada alasan pelanggan tidak dapat menginstal Python 3 pada VPS? Atau di 2016, apakah orang masih menggunakan shared hosting yang administratornya tidak mau menginstal Python 3? Misalnya, hosting bersama WebFaction telah python3.5diinstal.
Damian Yerrick
2
+1 untuk solusi yang juga berfungsi ketika input standar telah dialihkan dari file! Dengan solusi lain, saya mendapatkan Inappropriate ioctl for deviceerror / peringatan, atau mendapatkan nilai fallback yang didefinisikan sebesar 80.
pawamoy
65
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 termcaptersedia, ketika ya. Itu menggunakannya; jika tidak memeriksa apakah terminal mendukung ioctlpanggilan khusus dan itu tidak berfungsi juga, ia memeriksa variabel lingkungan yang diekspor oleh beberapa shell. Ini mungkin hanya akan bekerja pada UNIX.
Terima kasih atas balasan cepat, tetapi di sini ( effbot.org/zone/console-handbook.htm ) dikatakan bahwa "Modul Konsol saat ini hanya tersedia untuk Windows 95, 98, NT, dan 2000." Saya mencari solusi yang berfungsi di Linux. Mungkin tidak jelas dari tag, saya akan mengedit pertanyaan sesuai.
Sergey Golovchenko
2
karena modul "konsol" yang Anda gunakan ini tidak ada di pustaka python standar, Anda harus memberikan kode sumbernya atau setidaknya tautan ke sana.
nosklo
Aku turut berduka atas hal itu. Sebenarnya, saya tidak tahu modul itu. Saya mencoba mengimpor konsol dan berfungsi, saya menggunakan konsol. <tab> <tab> dan getTerminalSize () muncul. Alih-alih mencari di mana itu dari saya sudah diposting jawaban karena aku begitu beruntung dari kesederhanaan g
Johannes Weiss
Saya mungkin melihat modul "konsol" yang berbeda, dapatkah Anda memberikan tautan untuk yang Anda miliki?
Sergey Golovchenko
4
Oh, dan tidak menumpuk kode, tetapi "cr" adalah nama yang membingungkan karena itu menyiratkan tuple adalah (cols, rows). Pada kenyataannya, ini adalah kebalikannya.
Paul Du Bois
57
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:
Inilah yang harus dilakukan; perhatikan bahwa jika Anda berniat untuk mencetak ke terminal, Anda harus menggunakan '1' sebagai deskriptor file (argumen pertama ioctl), karena stdin mungkin berupa pipa atau tty yang berbeda.
mic_e
1
Mungkin 0 harus diganti denganfcntl.ioctl(sys.stdin.fileno(), ...
raylu
4
ini adalah jawaban terbaik - pengguna Anda akan senang bahwa tidak ada subproses kejutan terjadi hanya untuk mendapatkan lebar istilah
zzzeek
4
ini memang jawaban terbersih. Saya pikir Anda harus menggunakan stdoutatau stderrbukannya stdin. stdinmungkin pipa. Anda mungkin juga ingin menambahkan baris seperti if not os.isatty(0): return float("inf").
mic_e
ini entah bagaimana berfungsi pada terminal chromebook yang tidak memiliki fungsi. +1
HyperNeutrino
39
Saya mencari-cari dan menemukan solusi untuk windows di:
The shutilFungsi hanya bungkus sekitar ossatu 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 0adalah 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.
shutil.get_terminal_size() is the high-level function which should normally be used, os.get_terminal_size is the low-level implementation.
mid_kid
1
Ini adalah salinan dekat dari jawaban setahun yang lebih tua yang diberikan di atas.
Gringo Suave
6
Sepertinya ada beberapa masalah dengan kode itu, Johannes:
getTerminalSize perlu import os
apa env? Sepertinya os.environ.
Juga, mengapa beralih linesdan colssebelum kembali? Jika TIOCGWINSZdan sttykeduanya mengatakan linesitu 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, stderrfor 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 variablestry:return tuple(int(os.getenv(var))for var in("LINES","COLUMNS"))except:pass# i give up. return default.return(25,80)
Saya juga berkeliaran tentang hal envitu, dan memang env = os.environ, dari jawaban yang diterima .
sdaau
6
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()
Namun ini gagal bagi saya karena saya sedang mengerjakan skrip yang mengharapkan input diarahkan pada stdin, dan sttyakan 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()
Saya mencari hal yang sama. Sangat mudah digunakan dan menawarkan alat untuk mewarnai, menata dan memposisikan di terminal. Yang Anda butuhkan semudah:
from blessings importTerminal
t =Terminal()
w = t.width
h = t.height
Bekerja seperti pesona di Linux. (Saya tidak yakin tentang MacOSX dan Windows)
Saat ini saya akan mengatakan mencoba "diberkati" yang merupakan garpu (dan peningkatan) "berkat" yang saat ini dikelola.
zezollo
1
@ reannual's jawaban berfungsi dengan baik, tetapi ada masalah dengan itu: os.popensekarang sudah usang . The subprocessModul harus digunakan sebagai gantinya, jadi di sini adalah versi kode @ reannual yang menggunakan subprocessdan langsung menjawab pertanyaan (dengan memberikan lebar kolom secara langsung sebagai int:
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 Screenkelas Anda dan gunakan dimensionsproperti 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))
Jawaban:
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+)
sumber
rows, columns = subprocess.check_output(['stty', 'size']).split()
sedikit lebih pendek, ditambah subproses adalah masa depanrows, columns = subprocess.check_output(['stty', 'size']).decode().split()
Jika Anda ingin string unicode untuk kompatibilitas py2 / 3Tidak yakin mengapa itu ada dalam modul
shutil
, tetapi ia mendarat di Python 3.3, menanyakan ukuran terminal keluaran :Implementasi tingkat rendah ada di modul os. Juga berfungsi di Windows.
Backport sekarang tersedia untuk Python 3.2 dan di bawah:
sumber
python3.5
diinstal.Inappropriate ioctl for device
error / peringatan, atau mendapatkan nilai fallback yang didefinisikan sebesar 80.menggunakan
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 mendukungioctl
panggilan khusus dan itu tidak berfungsi juga, ia memeriksa variabel lingkungan yang diekspor oleh beberapa shell. Ini mungkin hanya akan bekerja pada UNIX.sumber
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:
hp dan hp harus mengandung lebar dan tinggi piksel, tetapi tidak.
sumber
fcntl.ioctl(sys.stdin.fileno(), ...
stdout
ataustderr
bukannyastdin
.stdin
mungkin pipa. Anda mungkin juga ingin menambahkan baris sepertiif 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:
sumber
Itu baik:
The
shutil
Fungsi hanya bungkus sekitaros
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.
sumber
os.get_terminal_size()
diperkenalkan dalam Python 3.3os.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
sumber
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
perluimport os
env
? Sepertinyaos.environ
.Juga, mengapa beralih
lines
dancols
sebelum kembali? JikaTIOCGWINSZ
danstty
keduanya mengatakanlines
itucols
, 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:
sumber
env
itu, dan memangenv = os.environ
, dari jawaban yang diterima .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.
sumber
Saya sedang mencoba solusi dari sini yang memanggil ke
stty size
: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:
sumber
Coba "berkah"
Saya mencari hal yang sama. Sangat mudah digunakan dan menawarkan alat untuk mewarnai, menata dan memposisikan di terminal. Yang Anda butuhkan semudah:
Bekerja seperti pesona di Linux. (Saya tidak yakin tentang MacOSX dan Windows)
Unduh dan dokumentasi di sini
atau Anda dapat menginstalnya dengan pip:
sumber
@ reannual's jawaban berfungsi dengan baik, tetapi ada masalah dengan itu:
os.popen
sekarang sudah usang . Thesubprocess
Modul harus digunakan sebagai gantinya, jadi di sini adalah versi kode @ reannual yang menggunakansubprocess
dan langsung menjawab pertanyaan (dengan memberikan lebar kolom secara langsung sebagaiint
:Diuji pada OS X 10.9
sumber
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 gunakandimensions
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.
sumber
Ini adalah versi yang seharusnya kompatibel dengan Linux dan Solaris. Berdasarkan posting dan komitmen dari madchine . Membutuhkan modul subproses.
sumber