มีวิธีใดในไพ ธ อนที่จะกำหนดความกว้างของคอนโซลโดยทางโปรแกรมหรือไม่ ฉันหมายถึงจำนวนตัวอักษรที่พอดีในหนึ่งบรรทัดโดยไม่มีการตัดคำไม่ใช่ความกว้างของพิกเซลของหน้าต่าง
แก้ไข
กำลังมองหาโซลูชันที่ใช้งานได้กับ Linux
มีวิธีใดในไพ ธ อนที่จะกำหนดความกว้างของคอนโซลโดยทางโปรแกรมหรือไม่ ฉันหมายถึงจำนวนตัวอักษรที่พอดีในหนึ่งบรรทัดโดยไม่มีการตัดคำไม่ใช่ความกว้างของพิกเซลของหน้าต่าง
แก้ไข
กำลังมองหาโซลูชันที่ใช้งานได้กับ Linux
คำตอบ:
import os
rows, columns = os.popen('stty size', 'r').read().split()
ใช้คำสั่ง 'stty size' ซึ่งเป็นไปตามเธรดในรายการส่งเมลของ Python ซึ่งเป็นสากลที่สมเหตุสมผลบน linux มันเปิดคำสั่ง 'ขนาด stty' เป็นไฟล์ 'อ่าน' จากมันและใช้การแบ่งสตริงแบบง่ายเพื่อแยกพิกัด
ต่างจากค่า os.environ ["COLUMNS"] (ซึ่งฉันไม่สามารถเข้าถึงได้แม้จะใช้ bash เป็นเชลล์มาตรฐานของฉัน) ข้อมูลจะเป็นข้อมูลที่ทันสมัยในขณะที่ฉันเชื่อว่า os.environ ["COLUMNS"] ค่าจะใช้ได้เฉพาะในช่วงเวลาของการเปิดตัว python interpreter (สมมติว่าผู้ใช้ปรับขนาดหน้าต่างตั้งแต่นั้นมา)
(ดูคำตอบโดย @GringoSuave เกี่ยวกับวิธีการทำเช่นนี้กับ python 3.3+)
rows, columns = subprocess.check_output(['stty', 'size']).split()
สั้นกว่าเล็กน้อยบวกกับกระบวนการย่อยคืออนาคต
rows, columns = subprocess.check_output(['stty', 'size']).decode().split()
ถ้าคุณต้องการสตริง unicode สำหรับความเข้ากันได้ของ py2 / 3
ไม่แน่ใจว่าทำไมมันอยู่ในโมดูลshutil
แต่มันมาถึงที่นั่นใน Python 3.3 การสอบถามขนาดของเทอร์มินัลเอาท์พุท :
>>> import shutil
>>> shutil.get_terminal_size((80, 20)) # pass fallback
os.terminal_size(columns=87, lines=23) # returns a named-tuple
การใช้งานในระดับต่ำอยู่ในโมดูลระบบปฏิบัติการ ยังใช้งานได้ใน Windows
ขณะนี้มี backport สำหรับ Python 3.2 และด้านล่าง:
python3.5
ติดตั้งแล้ว
Inappropriate ioctl for device
ข้อผิดพลาด / คำเตือนหรือรับค่าทางเลือกที่กำหนดไว้ที่ 80
ใช้
import console
(width, height) = console.getTerminalSize()
print "Your terminal's width is: %d" % width
แก้ไข : โอ้ฉันขอโทษ นี่ไม่ใช่ lib มาตรฐานของไพ ธ อนนี่คือที่มาของ console.py (ฉันไม่รู้ว่ามาจากไหน)
โมดูลดูเหมือนจะทำงานดังนี้: ตรวจสอบว่าtermcap
มีให้หรือไม่เมื่อใช่ มันใช้สิ่งนั้น ถ้าไม่มีมันจะตรวจสอบว่าเทอร์มินัลรองรับการioctl
โทรพิเศษและไม่สามารถใช้งานได้เช่นกันมันจะตรวจสอบตัวแปรสภาพแวดล้อมที่บางเชลล์ส่งออกไป สิ่งนี้อาจใช้ได้กับ 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])
โค้ดด้านบนไม่ส่งคืนผลลัพธ์ที่ถูกต้องบน linux ของฉันเพราะ winsize-struct มีกางเกงขาสั้น 4 ตัวที่ไม่ได้ลงนามไม่ใช่กางเกงขาสั้น 2 ลายเซ็น:
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 และ hp ควรมีความกว้างและความสูงของพิกเซล แต่ไม่ใช่
fcntl.ioctl(sys.stdin.fileno(), ...
stdout
หรือstderr
แทนstdin
แม้ว่า stdin
อาจเป็นท่อได้เป็นอย่างดี if not os.isatty(0): return float("inf")
นอกจากนี้คุณยังอาจต้องการที่จะเพิ่มบรรทัดเช่น
ฉันค้นหารอบ ๆ และพบวิธีแก้ปัญหาสำหรับ windows ที่:
http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/
และทางออกสำหรับ linux ที่นี่
ดังนั้นนี่คือเวอร์ชันที่ใช้งานได้ทั้งบน linux, os x และ 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
มันทั้ง:
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
shutil
ฟังก์ชั่นเป็นเพียงเสื้อคลุมรอบos
หนึ่งที่จับข้อผิดพลาดบางและการตั้งค่าสำรอง แต่ก็มีหนึ่งข้อแม้มาก - จะแบ่งเมื่อท่อ! ซึ่งเป็นเรื่องใหญ่มาก
เพื่อรับขนาดเทอร์มินัลเมื่อใช้ท่อos.get_terminal_size(0)
แทน
อาร์กิวเมนต์แรก0
คืออาร์กิวเมนต์ที่ระบุว่าควรใช้ stdin file descriptor แทนค่าดีฟอลต์ stdout เราต้องการใช้ stdin เพราะ stdout แยกตัวเองเมื่อมันถูก piped ซึ่งในกรณีนี้ทำให้เกิดข้อผิดพลาด
ฉันพยายามคิดออกว่าจะใช้ stdout แทนที่จะเป็นอาร์กิวเมนต์ stdin เมื่อไรและไม่รู้ว่าทำไมจึงเป็นค่าเริ่มต้นที่นี่
os.get_terminal_size()
เปิดตัวใน Python 3.3
os.get_terminal_size(0)
จะมีปัญหาหากคุณไปที่ stdin ลอง:echo x | python3 -c 'import os; print(os.get_terminal_size(0))'
เริ่มต้นที่ Python 3.3 ตรงไปตรงมา: 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.
ดูเหมือนว่ามีปัญหาบางอย่างกับรหัสนั้น Johannes:
getTerminalSize
ต้องการ import os
env
อะไร os.environ
ดูเหมือนว่านอกจากนี้ทำไมสลับlines
และcols
ก่อนกลับมา ถ้าTIOCGWINSZ
และstty
ทั้งคู่พูดเช่นlines
นั้นcols
ฉันก็บอกว่าปล่อยไว้อย่างนั้น เรื่องนี้ทำให้ฉันสับสน 10 นาทีก่อนที่ฉันจะสังเกตเห็นความไม่ลงรอยกัน
Sridhar ฉันไม่ได้รับข้อผิดพลาดนั้นเมื่อฉันส่งออก pip ฉันค่อนข้างมั่นใจว่ามันถูกจับได้อย่างถูกต้องในการลองยกเว้น
ปาสกาล"HHHH"
ไม่ทำงานบนเครื่องของฉัน แต่"hh"
ทำ ฉันมีปัญหาในการค้นหาเอกสารสำหรับฟังก์ชั่นนั้น ดูเหมือนว่ามันขึ้นอยู่กับแพลตฟอร์ม
chochem จัดตั้งขึ้น
นี่คือรุ่นของฉัน:
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)
การใช้งาน Python 2 จำนวนมากที่นี่จะล้มเหลวหากไม่มีเทอร์มินัลการควบคุมเมื่อคุณเรียกใช้สคริปต์นี้ คุณสามารถตรวจสอบ sys.stdout.isatty () เพื่อตรวจสอบว่านี่เป็นเทอร์มินัลหรือไม่ แต่จะแยกเคสออกเป็นจำนวนมากดังนั้นฉันเชื่อว่าวิธีที่ไพเราะที่สุดในการหาขนาดเทอร์มินัลคือการใช้แพคเกจ
import curses
w = curses.initscr()
height, width = w.getmaxyx()
ฉันกำลังลองวิธีแก้ปัญหาจากที่นี่ซึ่งเรียกไปที่stty size
:
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
อย่างไรก็ตามสิ่งนี้ล้มเหลวสำหรับฉันเพราะฉันทำงานกับสคริปต์ที่คาดว่าจะมีการเปลี่ยนเส้นทางอินพุตใน stdin และstty
จะบ่นว่า "stdin ไม่ใช่เทอร์มินัล" ในกรณีนั้น
ฉันสามารถทำให้มันทำงานเช่นนี้:
with open('/dev/tty') as tty:
height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
ลอง"พร"
ฉันกำลังมองหาสิ่งเดียวกัน มันใช้งานง่ายมากและมีเครื่องมือสำหรับการระบายสีจัดแต่งทรงผมและวางตำแหน่งในเครื่อง สิ่งที่คุณต้องการนั้นง่ายพอ ๆ กับ:
from blessings import Terminal
t = Terminal()
w = t.width
h = t.height
ทำงานได้อย่างมีเสน่ห์ใน Linux (ฉันไม่แน่ใจเกี่ยวกับ MacOSX และ Windows)
ดาวน์โหลดและเอกสารประกอบที่นี่
หรือคุณสามารถติดตั้งได้ด้วย pip:
pip install blessings
@ คำตอบ reannual ทำงานได้ดี แต่มีปัญหากับมันจะเลิกตอนนี้os.popen
subprocess
โมดูลควรจะนำมาใช้แทนเพื่อให้ที่นี่เป็นรุ่นของรหัส @ reannual ที่ใช้subprocess
โดยตรงและตอบคำถาม (โดยการให้ความกว้างของคอลัมน์โดยตรงเป็นint
:
import subprocess
columns = int(subprocess.check_output(['stty', 'size']).split()[1])
ทดสอบบน OS X 10.9
หากคุณใช้ Python 3.3 ขึ้นไปฉันขอแนะนำ built-in get_terminal_size()
ตามที่แนะนำแล้ว แต่ถ้าคุณจะติดอยู่กับรุ่นเก่าและต้องการวิธีง่ายๆที่ข้ามแพลตฟอร์มการทำเช่นนี้คุณสามารถใช้asciimatics แพ็คเกจนี้รองรับเวอร์ชั่นของ Python กลับไปที่ 2.7 และใช้ตัวเลือกที่คล้ายกับที่แนะนำไว้ข้างต้นเพื่อรับขนาดเทอร์มินัล / คอนโซลปัจจุบัน
เพียงสร้างScreen
ชั้นเรียนของคุณและใช้dimensions
คุณสมบัตินี้เพื่อให้ได้ความสูงและความกว้าง สิ่งนี้ได้รับการพิสูจน์แล้วว่าทำงานบน Linux, OSX และ Windows
โอ้ - และการเปิดเผยอย่างสมบูรณ์ที่นี่: ฉันเป็นผู้เขียนดังนั้นโปรดเปิดประเด็นใหม่หากคุณมีปัญหาในการทำให้เรื่องนี้ทำงานได้
นี่คือรุ่นที่ควรใช้กับ Linux และ Solaris ขึ้นอยู่กับการโพสต์และ commments จากmadchine ต้องการโมดูลย่อย
def termize (): นำเข้า shlex กระบวนการย่อยอีกครั้ง output = subprocess.check_output (shlex.split ('/ bin / stty -a')) m = re.search ('rows \ D + (? P \ d +); คอลัมน์ \ D + (? P \ d +);', เอาต์พุต) ถ้า m: ส่งคืน m.group ('แถว'), m.group ('คอลัมน์') เพิ่ม OSError ('การตอบสนองที่ไม่ดี:% s'% (เอาต์พุต))
>>> เงื่อนไข () ('40', '100')