पायथन में लिनक्स कंसोल विंडो चौड़ाई कैसे प्राप्त करें


264

क्या पायथन में एक तरह से प्रोग्राम को कंसोल की चौड़ाई निर्धारित करना है? मेरा मतलब है कि वर्णों की संख्या जो एक पंक्ति में बिना लपेटे फिट होती है, न कि खिड़की की पिक्सेल चौड़ाई।

संपादित करें

एक समाधान की तलाश है जो लिनक्स पर काम करता है


"स्तंभ पर निर्भर" मुद्रण तंत्र के अधिक व्यापक समाधान के लिए इस उत्तर को देखें। stackoverflow.com/questions/44129613/…
रिकार्डो पेट्रागलिया

जवाबों:


261
import os
rows, columns = os.popen('stty size', 'r').read().split()

'स्टेंट साइज' कमांड का उपयोग करता है जो कि अजगर मेलिंग सूची पर एक धागे के अनुसार काफी हद तक लिनक्स पर सार्वभौमिक है। यह एक फाइल के रूप में 'स्ट्टी साइज' कमांड को खोलता है, इससे 'रीड' होता है, और निर्देशांक को अलग करने के लिए एक सरल स्ट्रिंग विभाजन का उपयोग करता है।

Os.environ ["COLUMNS"] मूल्य के विपरीत (जो मैं अपने मानक शेल के रूप में बैश का उपयोग करने के बावजूद उपयोग नहीं कर सकता) डेटा भी अप-टू-डेट होगा जबकि मेरा मानना ​​है कि os.environ ["COLUMNS"] मान केवल अजगर दुभाषिया के लॉन्च के समय के लिए मान्य होगा (मान लीजिए कि उपयोगकर्ता ने तब से विंडो का आकार बदला है)।

(अजगर ३.३+ पर कैसे करें इस बारे में @GringoSuave द्वारा उत्तर देखें)


1
आप सोलारिस पर काम करने के लिए इसे प्राप्त कर सकते हैं यदि "आकार" के बजाय आप "-ए" पास करते हैं। अर्धविराम सीमांकित आउटपुट में "पंक्तियां = वाई; कॉलम = एक्स" होगी।
जोसेफ गार्विन

5
COLUMNS को बश में डिफ़ॉल्ट रूप से निर्यात नहीं किया जाता है, इसीलिए os.environ ["COLUMNS"] काम नहीं करता है।
केजेल एंड्रियासेन

38
rows, columns = subprocess.check_output(['stty', 'size']).split()थोड़ा छोटा है, प्लस
सबप्रोसेस

7
tty स्टाइटी से बेहतर है, क्योंकि स्टिप PIPE के साथ काम नहीं कर सकता है।
liuyang1

5
rows, columns = subprocess.check_output(['stty', 'size']).decode().split()यदि आप py2 / 3 संगतता के लिए यूनिकोड स्ट्रिंग्स चाहते हैं
ब्रायस गुइंटा

264

यह निश्चित नहीं है कि यह मॉड्यूल में क्यों है shutil, लेकिन यह पायथन 3.3 में उतरा, आउटपुट टर्मिनल के आकार को छोड़कर :

>>> import shutil
>>> shutil.get_terminal_size((80, 20))  # pass fallback
os.terminal_size(columns=87, lines=23)  # returns a named-tuple

ओएस मॉड्यूल में एक निम्न-स्तरीय कार्यान्वयन है। विंडोज में भी काम करता है।

एक बैकपोर्ट अब पायथन 3.2 और उससे नीचे के लिए उपलब्ध है:


25
ऐसा इसलिए है क्योंकि आप किसी भी लंबे समय तक 2.7 का उपयोग नहीं कर रहे हैं, 3.x पर कूदें, यह इसके लायक है।
anthonyryan1

5
@osirisgothra कई होस्टिंग प्रदाता अभी तक python3 का समर्थन नहीं करते हैं, इसलिए हम में से कुछ बैक एंड डेवलपमेंट के लिए python2 का उपयोग करने के लिए मजबूर हैं। हालांकि इसका टर्मिनल साइज हासिल करने से कोई लेना-देना नहीं होना चाहिए ...
व्हाइटबर्ड

4
@osirisgothra क्योंकि पायथन 2 कोड का एक बहुत कुछ है जो पोर्ट के लिए बहुत अधिक काम करेगा। इसके अलावा, Pypy में अभी भी पायथन 3 का समर्थन नहीं है।
एंटीमनी

2
@whitebeard क्या कोई कारण है कि ग्राहक एक वीपीएस पर पायथन 3 स्थापित नहीं कर सकता है? या 2016 में, क्या लोग अभी भी साझा होस्टिंग का उपयोग कर रहे हैं जिसका व्यवस्थापक पायथन 3 स्थापित करने के लिए तैयार नहीं है? उदाहरण के लिए, WebFaction साझा होस्टिंग python3.5स्थापित किया है।
डेमियन येरिक

2
एक समाधान के लिए +1 जो मानक इनपुट को फ़ाइल से पुनर्निर्देशित करने पर भी काम करता है! अन्य समाधानों के साथ, मुझे या तो Inappropriate ioctl for deviceत्रुटियां / चेतावनियाँ मिल रही थीं, या 80 की परिभाषित फ़ालबैक वैल्यू मिल रही थी।
pawamoy

65

उपयोग

import console
(width, height) = console.getTerminalSize()

print "Your terminal's width is: %d" % width

संपादित करें : ओह, मुझे क्षमा करें। यह एक पायथन स्टैंडर्ड लिबास नहीं है, यहाँ कंसोलहोम का स्रोत है (मुझे नहीं पता कि यह कहाँ से है)।

मॉड्यूल इस तरह काम करता है: यह जांचता है कि 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])

5
त्वरित उत्तर के लिए धन्यवाद, लेकिन यहाँ ( effbot.org/zone/console-handbook.htm ) यह कहता है कि "कंसोल मॉड्यूल वर्तमान में केवल विंडोज 95, 98, NT और 2000 के लिए उपलब्ध है।" मैं एक समाधान की तलाश कर रहा हूं जो लिनक्स पर काम करता है। यह शायद टैग से स्पष्ट नहीं था, मैं तदनुसार प्रश्न को संपादित करूंगा।
सर्गेई गोलोवचेंको

2
चूंकि यह "कंसोल" मॉड्यूल जो आप उपयोग कर रहे हैं, मानक पायथन लाइब्रेरी पर नहीं है, आपको इसका स्रोत कोड या कम से कम एक लिंक प्रदान करना चाहिए।
nosklo

मुझे उसका बेहद अफसोस है। वास्तव में, मैं उस मॉड्यूल को नहीं जानता था। मैंने आयात कंसोल की कोशिश की और यह काम किया, मैंने कंसोल का उपयोग किया। <टैब> <टैब> और getTerminalSize () दिखाया। यह देखने के बजाय कि यह कहाँ से है, मैंने पहले से ही एक उत्तर पोस्ट कर दिया है क्योंकि मैं सादगी जी
जोहान्स वीस

मैं एक अलग "कंसोल" मॉड्यूल को देख सकता हूं, क्या आप अपने पास के लिए एक लिंक प्रदान कर सकते हैं?
सर्गेई गोलोवचेंको

4
ओह, और कोड पर ढेर करने के लिए नहीं, लेकिन "cr" एक भ्रामक नाम है क्योंकि इसका मतलब है कि टपल है (कॉल, पंक्तियाँ)। वास्तव में, यह उल्टा है।
पॉल डू बोइस

57

ऊपर कोड मेरे लिनक्स पर सही परिणाम नहीं लौटा क्योंकि जीत-संरचना में 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 में पिक्सेल चौड़ाई और ऊँचाई होनी चाहिए, लेकिन नहीं।


4
यह इस तरह से किया जाना चाहिए; ध्यान दें कि यदि आप टर्मिनल पर प्रिंट करने का इरादा रखते हैं, तो आपको फ़ाइल डिस्क्रिप्टर (ioctl का पहला तर्क) के रूप में '1' का उपयोग करना चाहिए, क्योंकि स्टड एक पाइप या कुछ अलग प्रकार का हो सकता है।
माइक_

1
शायद 0 से बदल जाना चाहिएfcntl.ioctl(sys.stdin.fileno(), ...
raylu

4
यह सबसे अच्छा जवाब है - आपके उपयोगकर्ता इस बात से खुश होंगे कि कोई आश्चर्यचकित करने वाला
उपप्रकार

4
यह वास्तव में सबसे साफ जवाब है। मुझे लगता है कि आपको उपयोग करना चाहिए stdoutया stderrइसके बजाय stdin, हालांकि। stdinबहुत अच्छी तरह से एक पाइप हो सकता है। आप इस तरह की एक लाइन भी जोड़ना चाह सकते हैं if not os.isatty(0): return float("inf")
mic_e

यह किसी तरह एक क्रोमबुक टर्मिनल पर काम करता है जिसमें कोई कार्यक्षमता नहीं है। +1
हाइपरन्यूट्रीनो

39

मैंने आसपास खोजबीन की और खिड़कियों के लिए एक समाधान ढूंढा:

http://code.activestate.com/recipes/440694-determine-size-of-console-window-on-windows/

और यहाँ लिनक्स के लिए एक समाधान।

तो यहाँ एक संस्करण है जो 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

आपने मुझे खुद ऐसा करने का समय दिया। लिनक्स पर काम करता है। विंडोज पर भी काम करना चाहिए। धन्यवाद!
स्टीव वी।

30

यह या तो:

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एक तर्क है जो यह दर्शाता है कि स्टडिन फाइल डिस्क्रिप्टर का उपयोग डिफ़ॉल्ट स्टडआउट के बजाय किया जाना चाहिए। हम स्टडिन का उपयोग करना चाहते हैं क्योंकि स्टडआउट तभी पाइप करता है जब उसे पाइप किया जा रहा होता है जो इस मामले में त्रुटि उठाता है।

मैंने यह पता लगाने की कोशिश की है कि स्टड तर्क के बजाय stdout का उपयोग करना कब समझ में आएगा और पता नहीं क्यों यह यहां एक डिफ़ॉल्ट है।


3
os.get_terminal_size()पायथन 3.3 में शुरू किया गया था
विलाप

मैंने पहली बार बंद करने की कोशिश की, और इसने पहली कोशिश की। मैं पाइथन 3.6+ का उपयोग कर रहा हूं।
दान

os.get_terminal_size(0)यदि आप स्टड करने के लिए पाइप करते हैं तो दुर्घटनाग्रस्त हो जाएगा। कोशिश करें:echo x | python3 -c 'import os; print(os.get_terminal_size(0))'
एहबाक नोस्ट

19

पायथन 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

16
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
यह ऊपर दिए गए एक साल पुराने उत्तर की एक निकट प्रति है।
ग्रिंगो सुवे

6

ऐसा लगता है कि उस कोड के साथ कुछ समस्याएं हैं, जोहान्स:

  • getTerminalSize की आवश्यकता है import os
  • क्या है env? जैसा दिखता है os.environ

इसके अलावा, क्यों स्विच करें linesऔर colsलौटने से पहले? अगर TIOCGWINSZऔर sttyदोनों कहते हैं , linesतो colsमैं कहता हूं कि इसे छोड़ दो। इससे पहले कि मैं असंगति पर ध्यान देता, 10 मिनट के लिए मुझे भ्रमित कर देता।

श्रीधर, जब मुझे आउटपुट मिला तो मुझे वह त्रुटि नहीं मिली। मुझे पूरा यकीन है कि यह कोशिश को छोड़कर ठीक से पकड़ा जा रहा है।

पास्कल, "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)

मैं भी भटक रहा था env, और यह वास्तव में env = os.environ, स्वीकृत उत्तर से है
सदाउ

6

जब आप इस स्क्रिप्ट को कॉल करते हैं तो कोई नियंत्रण टर्मिनल नहीं है, तो यहां पायथन 2 के कई कार्यान्वयन विफल हो जाएंगे। आप यह निर्धारित करने के लिए कि क्या वास्तव में एक टर्मिनल है, यह निर्धारित करने के लिए आप sys.stdout.isatty () की जांच कर सकते हैं, लेकिन यह मामलों के एक समूह को बाहर कर देगा, इसलिए मेरा मानना ​​है कि टर्मिनल आकार का पता लगाने के लिए सबसे पायथोनिक तरीका अंतर्निहित शाप पैकेज का उपयोग करना है।

import curses
w = curses.initscr()
height, width = w.getmaxyx()

2

मैं यहाँ से समाधान की कोशिश कर रहा था कि बाहर करने के लिए कॉल stty size:

columns = int(subprocess.check_output(['stty', 'size']).split()[1])

हालाँकि यह मेरे लिए विफल रहा क्योंकि मैं एक स्क्रिप्ट पर काम कर रहा था जो स्टड पर पुनर्निर्देशित इनपुट की अपेक्षा करता है, और sttyशिकायत करेगा कि उस मामले में "स्टडिन एक टर्मिनल नहीं है"।

मैं इसे इस तरह काम करने में सक्षम था:

with open('/dev/tty') as tty:
    height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()

2

"आशीर्वाद" का प्रयास करें

मैं उसी चीज की तलाश में था। टर्मिनल में रंग, स्टाइल और पोजिशनिंग के लिए टूल्स का उपयोग करना बहुत आसान है। क्या आप की जरूरत के रूप में आसान है:

from blessings import Terminal

t = Terminal()

w = t.width
h = t.height

लिनक्स में एक आकर्षण की तरह काम करता है। (मैं MacOSX और विंडोज के बारे में निश्चित नहीं हूं)

डाउनलोड और प्रलेखन यहाँ

या आप इसे पाइप से स्थापित कर सकते हैं:

pip install blessings

आजकल मैं कहूंगा कि "धन्य" की कोशिश करें जो वर्तमान में "आशीर्वाद" का कांटा (और वृद्धि) है।
zezollo

1

@ reannual का उत्तर अच्छी तरह से काम करता है, लेकिन इसके साथ एक मुद्दा है: os.popen अब हटा दिया गया है । इसके subprocessबजाय मॉड्यूल का उपयोग किया जाना चाहिए, इसलिए यहाँ @ reannual के कोड का एक संस्करण है जो subprocessसीधे उपयोग करता है और सीधे प्रश्न का उत्तर देता है (स्तंभ की चौड़ाई को सीधे रूप से int:

import subprocess

columns = int(subprocess.check_output(['stty', 'size']).split()[1])

OS X 10.9 पर परीक्षण किया गया


1

यदि आप Python 3.3 या इसके बाद के संस्करण का उपयोग कर रहे हैं, तो मैं get_terminal_size()पहले से ही सुझाए गए अंतर्निहित निर्माण की सलाह दूंगा। हालाँकि यदि आप एक पुराने संस्करण के साथ फंस गए हैं और ऐसा करने का एक सरल, क्रॉस-प्लेटफ़ॉर्म तरीका चाहते हैं, तो आप एसिसिमेटिक्स का उपयोग कर सकते हैं । यह पैकेज 2.7 के पीछे पायथन के संस्करणों का समर्थन करता है और मौजूदा टर्मिनल / कंसोल आकार प्राप्त करने के लिए ऊपर सुझाए गए समान विकल्पों का उपयोग करता है।

बस अपनी Screenकक्षा का निर्माण करें और dimensionsऊंचाई और चौड़ाई प्राप्त करने के लिए संपत्ति का उपयोग करें । यह लिनक्स, OSX और विंडोज पर काम करने के लिए सिद्ध हुआ है।

ओह - और पूर्ण प्रकटीकरण यहां: मैं लेखक हूं, इसलिए कृपया एक नया मुद्दा खोलने के लिए स्वतंत्र महसूस करें यदि आपके पास काम करने के लिए कोई समस्या है।


0

यहां एक संस्करण है जो लिनक्स और सोलारिस संगत होना चाहिए। मैडचिन से पदों और स्मारकों के आधार पर । उपप्रक्रम मॉड्यूल की आवश्यकता है।

डिफाइंड डिफ़ेक्ट ():
    आयात shlex, उपप्रकार, पुनः
    आउटपुट = सबप्रोसेस.चेक_आउट (shlex.split ('/ bin / stty -a'))
    m = re.search ('पंक्तियों \ D + (; P \ d +); कॉलम \ D + ((? P d d +);', आउटपुट)
    यदि एम:
        वापसी m.group ('पंक्तियाँ'), m.group ('कॉलम')
    OSError बढ़ाएँ ('खराब प्रतिक्रिया:% s'% (आउटपुट))
>>> संक्षिप्त करें ()
('40', '100')
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.