Python'da konsolun genişliğini programlı olarak belirlemenin bir yolu var mı? Pencerenin piksel genişliğine değil, bir satıra sığmayan karakter sayısını kastediyorum.
Düzenle
Linux'ta çalışan bir çözüm mü arıyorsunuz
Python'da konsolun genişliğini programlı olarak belirlemenin bir yolu var mı? Pencerenin piksel genişliğine değil, bir satıra sığmayan karakter sayısını kastediyorum.
Düzenle
Linux'ta çalışan bir çözüm mü arıyorsunuz
Yanıtlar:
import os
rows, columns = os.popen('stty size', 'r').read().split()
python posta listesindeki bir iş parçacığına göre linux üzerinde oldukça evrensel olan 'stty size' komutunu kullanır . 'Stty size' komutunu bir dosya olarak açar, 'okur' ve koordinatları ayırmak için basit bir dize kullanır.
Os.environ ["COLUMNS"] değerinin (bash'ı standart kabuğum olarak kullanmamıza rağmen erişemiyorum) aksine, veriler de güncel olurken os.environ ["COLUMNS"] değeri yalnızca python yorumlayıcısının başlatılma zamanı için geçerli olacaktır (kullanıcının pencereyi o zamandan beri yeniden boyutlandırdığını varsayalım).
(@GringoSuave tarafından python 3.3 ve sonrasında bunun nasıl yapılacağı ile ilgili cevaba bakınız)
rows, columns = subprocess.check_output(['stty', 'size']).split()
biraz daha kısa, artı alt süreç gelecek
rows, columns = subprocess.check_output(['stty', 'size']).decode().split()
Py2 / 3 uyumluluğu için unicode dizeleri istiyorsanız
Modülde neden olduğundan emin değilim shutil
, ancak çıkış terminalinin boyutunu sorgulayarak Python 3.3'e indi :
>>> import shutil
>>> shutil.get_terminal_size((80, 20)) # pass fallback
os.terminal_size(columns=87, lines=23) # returns a named-tuple
OS modülünde düşük düzeyli bir uygulama vardır. Windows'da da çalışır.
Python 3.2 ve daha önceki sürümler için bir backport mevcut:
python3.5
yüklendi.
Inappropriate ioctl for device
hata / uyarı alıyordum ya da 80 tanımlı geri dönüş değerini
kullanım
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
EDIT : oh, özür dilerim. Bu bir python standart lib olanı değil, işte console.py kaynağı (nereden geldiğini bilmiyorum).
Modül şöyle çalışıyor: Varsa termcap
, mevcut olup olmadığını kontrol eder . Bunu kullanır; hayır ise, terminalin özel bir ioctl
çağrıyı destekleyip desteklemediğini kontrol eder ve bu da çalışmaz, bazı kabukların dışa aktardığı ortam değişkenlerini kontrol eder. Bu muhtemelen yalnızca UNIX üzerinde çalışacaktır.
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])
Yukarıdaki kod linux'umda doğru sonucu döndürmedi çünkü winsize-struct'un 2 imzasız şortu var, 2 imzalı şortu yok:
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 ve hp piksel genişliği ve yüksekliği içermelidir, ancak içermemelidir.
fcntl.ioctl(sys.stdin.fileno(), ...
stdout
ya da stderr
yerine kullanmanız gerektiğini düşünüyorum stdin
. stdin
çok iyi bir boru olabilir. Gibi bir satır eklemek de isteyebilirsiniz if not os.isatty(0): return float("inf")
.
Etrafı araştırdım ve Windows için bir çözüm buldum:
http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/
ve burada linux için bir çözüm.
İşte hem linux, os x hem de windows / cygwin üzerinde çalışan bir sürüm:
""" 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
O da:
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
shutil
Fonksiyon etrafında sarıcı olduğunu os
ancak bir büyük ihtar vardır, bazı hatalar yakalar ve bir yedek özelliğini kurmak one - o zaman boru tesisatı kırar! Bu oldukça büyük bir anlaşma.
Borulama sırasında terminal boyutunu almak için os.get_terminal_size(0)
kullanın.
İlk argüman 0
, varsayılan stdout yerine stdin dosya tanımlayıcısının kullanılması gerektiğini belirten bir argüman. Stdin'i kullanmak istiyoruz çünkü stdout, boru döşenirken kendisini ayırır, bu durumda bir hata oluşturur.
Stdin argümanı yerine stdout kullanmanın ne zaman mantıklı olduğunu anlamaya çalıştım ve burada neden varsayılan olduğunu bilmiyorum.
os.get_terminal_size()
Python 3.3'te tanıtıldı
os.get_terminal_size(0)
Eğer boru stdin'i eğer kilitlenmesine. Deneyin:echo x | python3 -c 'import os; print(os.get_terminal_size(0))'
Python 3.3'ten başlayarak basittir: 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.
Görünüşe göre bu kodla ilgili bazı sorunlar var Johannes:
getTerminalSize
ihtiyacı olmak import os
env
? gibi görünüyor os.environ
.Ayrıca, neden geçmeli lines
ve cols
geri dönmeden önce? Eğer TIOCGWINSZ
ve stty
ikisi de demek lines
o zaman cols
, ben bu şekilde bırakmak demek. Bu tutarsızlığı fark etmeden önce 10 dakika boyunca beni şaşırttı.
Sridhar, çıktıyı borsalarken bu hatayı almadım. Eminim denemede düzgün bir şekilde yakalandığından eminim.
pascal, "HHHH"
makinemde "hh"
çalışmıyor , ama çalışıyor . Bu işlevin belgelerini bulmakta sorun yaşadım. Görünüşe göre platforma bağımlı.
chochem, dahil.
İşte benim versiyonum:
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)
Bu komut dosyasını çağırdığınızda kontrol terminali yoksa Python 2 uygulamalarının çoğu başarısız olur. Bu aslında bir terminal olup olmadığını belirlemek için sys.stdout.isatty () kontrol edebilirsiniz, ancak bu bir grup durumda dışlayacak, bu yüzden terminal boyutunu anlamanın en pitonik yolunun yerleşik curses paketini kullanmak olduğuna inanıyorum.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
Buradan çağıran çözümü deniyordum stty size
:
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
Ancak bu benim için başarısız oldu çünkü stdin üzerine yeniden yönlendirilmiş girdi bekleyen bir komut dosyası üzerinde çalışıyordu ve stty
bu durumda "stdin bir terminal değil" şikayet ediyorum.
Bu şekilde çalışmasını sağlayabildim:
with open('/dev/tty') as tty:
height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
"Bereket" i deneyin
Ben de aynı şeyi arıyordum. Kullanımı çok kolaydır ve terminalde renklendirme, şekillendirme ve konumlandırma için araçlar sunar. İhtiyacınız olan şey şu kadar kolaydır:
from blessings import Terminal
t = Terminal()
w = t.width
h = t.height
Linux'ta bir cazibe gibi çalışır. (MacOSX ve Windows hakkında emin değilim)
İndirme ve dokümantasyon burada
veya pip ile kurabilirsiniz:
pip install blessings
@ reannual'ın cevabı iyi çalışıyor, ancak bununla ilgili bir sorun var: os.popen
şimdi kullanımdan kaldırıldı . Bunun subprocess
yerine modül kullanılmalıdır, bu yüzden subprocess
soruyu kullanan ve doğrudan cevaplayan @ reannual kodunun bir sürümü ( sütun genişliğini doğrudan şöyle vererek int
:
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
OS X 10.9'da test edilmiştir
Python 3.3 veya üstünü kullanıyorsanız, dahili get_terminal_size()
olarak tavsiye edilen şekilde öneriyorum. Bununla birlikte, daha eski bir sürümle sıkışıp kalırsanız ve bunu yapmanın basit, platformlar arası bir yolunu istiyorsanız, siyatik kullanabilirsiniz . Bu paket Python'un 2.7'ye kadar olan sürümlerini destekler ve geçerli terminal / konsol boyutunu elde etmek için yukarıda önerilenlere benzer seçenekler kullanır.
Sadece Screen
sınıfınızı oluşturun ve dimensions
yüksekliği ve genişliği elde etmek için özelliği kullanın. Bunun Linux, OSX ve Windows üzerinde çalıştığı kanıtlanmıştır.
Oh - ve tam açıklama burada: Ben yazarım, bu yüzden bu işe yarayan herhangi bir sorun varsa yeni bir sorun açmak için çekinmeyin.
Linux ve Solaris uyumlu olması gereken bir sürüm. Madchine yazı ve taahhütlerine dayanarak . Alt işlem modülünü gerektirir.
def termsize (): shlex, alt süreç, yeniden içe aktarma output = subprocess.check_output (shlex.split ('/ bin / stty -a')) m = yeniden arama ('satırlar \ D + (? P \ d +); sütunlar \ D + (? P \ d +);', çıktı) eğer m: m.group ('satırlar'), m.group ('sütunlar') döndür OSError değerini yükselt ('Kötü yanıt:% s'% (çıktı))
>>> termsiz () ('40', '100')