كيفية الحصول على عرض نافذة Linux وحدة التحكم في بيثون

StackOverflow https://stackoverflow.com/questions/566746

سؤال

هل هناك طريقة في بيثون لتحديد عرض وحدة التحكم برمجيا؟ أعني عدد الأحرف التي تناسبها في سطر واحد دون التفاف، وليس عرض البكسل للنافذة.

يحرر

تبحث عن حل يعمل على لينكس

هل كانت مفيدة؟

المحلول

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

يستخدم الأمر "حجم Stty" الذي وفقا ل موضوع على قائمة Python البريدية هو عالمي بشكل معقول على لينكس. إنه يفتح الأمر "STTY SIZE" كملف، "يقرأ" منه، ويستخدم تقسيم سلسلة بسيط لفصل الإحداثيات.

على عكس قيمة OS.ENVIRY ["الأعمدة" ["الأعمدة"] (التي لا يمكنني الوصول إليها على الرغم من استخدام Bash كقذيفة قياسية) ستكون البيانات محدثة أيضا في حين أعتقد أن OS.Environ ["الأعمدة"] ستكون القيمة سارية فقط لوقت إطلاق مترجم الثعبان (لنفترض أن المستخدم تغيير حجم النافذة منذ ذلك الحين).

نصائح أخرى

لست متأكدا لماذا في الوحدة النمطية shutil, ، لكنه هبط هناك في بيثون 3.3، الاستعلام عن حجم محطة الإخراج:

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

التنفيذ المنخفض المستوى هو في وحدة OS.

أصبحت Backport متاحة الآن لبثيون 3.2 وما دون:

استعمال

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

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

تعديل: انا اسف. هذا ليس بيثون قياسي قياسي واحد، إليك مصدر 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-Britch يحتوي على 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 على عرض البكسل والطول، ولكن لا.

لقد بحثت حولها ووجدت حلا للنوافذ في:

http://code.activestate.com/recipes/440694-determine-size-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

ابتداء من Python 3.3 أنها مستقيمة إلى الأمام:https://docs.python.org/3/library/os.html#querying-the-size-of-a-terminal.minal.

>>> import os
>>> ts = os.get_terminal_size()
>>> ts.lines
24
>>> ts.columns
80

انها إما:

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 يجب استخدامه بدلا من Stdout الافتراضي. نريد استخدام Stdin لأن Stdout ينفصل عن نفسه عندما يجري أنابيب ما يرفع في هذه الحالة خطأ ..
لقد حاولت معرفة متى سيكون من المنطقي استخدام Stdout بدلا من حجة Stdin وليس لديك أي فكرة عن سبب ذلك الافتراضي هنا.

يبدو أن هناك بعض المشاكل مع هذا الكود، يوهانس:

  • 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)

ستفشل العديد من تطبيقات Python 2 هنا إذا لم يكن هناك محطة مراقبة عند استدعاء هذا البرنامج النصي. يمكنك التحقق من syss.stdout.isatty () لتحديد ما إذا كان هذا في الواقع محطة، ولكن هذا سيستبعد مجموعة من الحالات، لذلك أعتقد أن الطريقة الأكثر ثباتا لمعرفة حجم المحطة الطرفية هي استخدام حزمة لعنات المدمجة.

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

كنت أحاول الحل من هنا الذي يدعو إلى stty size:

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

ومع ذلك فشل هذا بالنسبة لي لأنني كنت أعمل على برنامج نصي يتوقع إدخال إعادة توجيه على Stdin، و stty سوف يشكو من أن "ستدين ليس محطة" في هذه الحالة.

كنت قادرا على جعلها تعمل مثل هذا:

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

إجابة @ Reinnual تعمل بشكل جيد، ولكن هناك مشكلة في ذلك: os.popen تم إهمالها الآن. وبعد ال subprocess يجب استخدام الوحدة النمطية بدلا من ذلك، إذن إليك إصدار من رمز @ Reannual الذي يستخدم subprocess وإجابات مباشرة السؤال (عن طريق إعطاء عرض العمود مباشرة ك int:

import subprocess

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

تم اختباره على نظام التشغيل X 10.9

يحاول "بركات"

كنت أبحث عن نفس الشيء. من السهل جدا استخدامها وتقدم أدوات للتلوين والتصميم وتحديد المواقع في المحطة. ما تحتاجه سهل مثل:

from blessings import Terminal

t = Terminal()

w = t.width
h = t.height

يعمل مثل سحر في لينكس. (لست متأكدا من ماكوسكس والنوافذ)

تحميل وتوثيق هنا

أو يمكنك تثبيته مع PIP:

pip install blessings

إذا كنت تستخدم Python 3.3 أو أعلى، فسوف أوصي المدمج get_terminal_size() كما أوصت بالفعل. ومع ذلك، إذا كنت عالقا مع إصدار أقدم وأريد طريقة بسيطة وعبر منصة للقيام بذلك، يمكنك استخدامها Asiimatics.. وبعد تدعم هذه الحزمة إصدارات Python مرة أخرى إلى 2.7 وتستخدم خيارات مماثلة لتلك المقترحة أعلاه للحصول على حجم المحطة / وحدة التحكم الحالية.

ببساطة بناء الخاص بك Screen الطبقة واستخدام dimensions الممتلكات للحصول على الارتفاع والعرض. وقد ثبت أن هذا يعمل على Linux و OSX و Windows.

أوه - والإفصاح الكامل هنا: أنا المؤلف، لذا لا تتردد في فتح مشكلة جديدة إذا كان لديك أي مشاكل في الحصول على هذا للعمل.

فيما يلي نسخة يجب أن تكون Linux و Solaris متوافق. بناء على المشاركات والكمال من مادشين. وبعد يتطلب وحدة الفرعية.

Sustice Def Soursize (): استيراد Sclex، subprocess، re الناتج = subprocess.check_output (shlex.split (shlex.split ('/ bin / stty -a')) m = re.search ('الصفوف + d + (؟ p  d +)؛ الأعمدة  D + (؟ p  d +)؛ "، الإخراج) إذا م: العودة M.Group (" الصفوف ")، و M.Group (" الأعمدة ") تثير OSERROR (استجابة سيئة:٪ S '٪ (الإخراج))
>>> بشرية () ('40'، '100')
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top