قراءة المدخلات من RAW_INPUT () دون أن يتم كتابة المطالبة فوقها بواسطة مؤشرات ترابط أخرى في Python

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

سؤال

أحاول السماح للمستخدم بإدخال أوامر إدخال في وحدة تحكم باستخدام RAW_INPUT () ، وهذا يعمل بشكل جيد. المشكلة هي أن لدي مؤشرات ترابط الخلفية التي تخرج من حين لآخر معلومات تسجيل الدخول إلى الشاشة وعندما تفعل ذلك ، فإنها تعبث موجه الإدخال (نظرًا لأن الإخراج يذهب إلى أي مكان يحدث فيه المؤشر في الوقت الحالي).

هذا هو برنامج Python صغير يوضح ما أعنيه.

#!/usr/bin/env python
import threading
import time

def message_loop():
    while True:
        time.sleep(1)
        print "Hello World"

thread = threading.Thread(target = message_loop)
thread.start()

while True:
    input = raw_input("Prompt> ")
    print "You typed", input

هذا مثال على شكله عندما أقوم بتشغيله:

Prompt> Hello World
Hello World
Hello World
Hello World
test
You typed test
Prompt> Hello World
Hello World
Hello World
hellHello World
o
You typed hello
Prompt> Hello World
Hello World
Hello World
Hello World

ما أريده هو أن يتحرك الموجه مع الإخراج من الخيط. مثل ذلك:

Hello World
Hello World
Prompt> test
You typed test
Hello World
Hello World
Hello World
Hello World
Hello World
Prompt> hello
You typed hello
Hello World
Hello World
Hello World
Hello World
Prompt> 

أي أفكار حول كيفية تحقيق ذلك دون اللجوء إلى الاختراقات القبيحة؟ قون

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

المحلول

لقد واجهت هذه المشكلة مؤخرًا ، وأرغب في ترك هذا الحل هنا للرجوع إليه في المستقبل. هذه الحلول مسح نص RAW_INPUT المعلق (READLINE) من المحطة ، طباعة النص الجديد ، ثم إعادة طبع إلى المحطة ما كان في المخزن المؤقت RAW_INPUT.

هذا البرنامج الأول بسيط للغاية ، ولكنه يعمل بشكل صحيح فقط عندما لا يوجد سوى سطر واحد من النص في انتظار RAW_INPUT:

#!/usr/bin/python

import time,readline,thread,sys

def noisy_thread():
    while True:
        time.sleep(3)
        sys.stdout.write('\r'+' '*(len(readline.get_line_buffer())+2)+'\r')
        print 'Interrupting text!'
        sys.stdout.write('> ' + readline.get_line_buffer())
        sys.stdout.flush()

thread.start_new_thread(noisy_thread, ())
while True:
    s = raw_input('> ')

انتاج:

$ ./threads_input.py
Interrupting text!
Interrupting text!
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
naparte family. No, I warn you, that if you do not tell me we are at war,

يعالج الثاني بشكل صحيح خطين أو أكثر من الخطوط المخزنة ، ولكن لديه المزيد من التبعيات (القياسية) ويتطلب جزءًا من الاختراق الطرفي:

#!/usr/bin/python

import time,readline,thread
import sys,struct,fcntl,termios

def blank_current_readline():
    # Next line said to be reasonably portable for various Unixes
    (rows,cols) = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,'1234'))

    text_len = len(readline.get_line_buffer())+2

    # ANSI escape sequences (All VT100 except ESC[0G)
    sys.stdout.write('\x1b[2K')                         # Clear current line
    sys.stdout.write('\x1b[1A\x1b[2K'*(text_len/cols))  # Move cursor up and clear line
    sys.stdout.write('\x1b[0G')                         # Move to start of line


def noisy_thread():
    while True:
        time.sleep(3)
        blank_current_readline()
        print 'Interrupting text!'
        sys.stdout.write('> ' + readline.get_line_buffer())
        sys.stdout.flush()          # Needed or text doesn't show until a key is pressed


if __name__ == '__main__':
    thread.start_new_thread(noisy_thread, ())
    while True:
        s = raw_input('> ')

انتاج. تم مسح خطوط القراءة السابقة بشكل صحيح:

$ ./threads_input2.py
Interrupting text!
Interrupting text!
Interrupting text!
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
naparte family. No, I warn you, that if you do not tell me we are at war,

مصادر مفيدة:

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

apt مثل إخراج العمود - مكتبة بيثون(توضح عينة الرمز كيفية الحصول على عرض طرفي إما لـ UNIX أو Windows)

http://en.wikipedia.org/wiki/ansi_escape_code

نصائح أخرى

أعتقد أنك بحاجة إلى شيء يتيح لك طباعة/حذف/الكتابة فوقها ديناميكيًا من النافذة الطرفية على سبيل المثال كيف يونيكس watch أو top الأوامر العمل.

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

قد تكون قادرًا على فعل ما تريد باستخدام Python's لعنات مكتبة. لم أستخدمها أبدًا ، لذا لا يمكنني إخبارك بكيفية حل مشكلتك (أو إذا كانت الوحدة قادرة على حل مشكلتك) ، لكنني أعتقد أن الأمر يستحق إلقاء نظرة عليها. بحث عن "Python Curses Tutorial" شريطة أ وثيقة تعليمية PDF الذي يبدو مفيدًا.

تحتاج إلى تحديث stdout من مؤشر ترابط واحد ، وليس من مؤشرات ترابط متعددة ... وإلا فلديك أي تحكم في I/O المتداخلة.

سترغب في إنشاء موضوع واحد لكتابة الإخراج.

يمكنك استخدام قائمة انتظار في مؤشر الترابط وجعل جميع مؤشرات الترابط الأخرى تكتب معلومات تسجيل الإخراج الخاصة بها .. ثم اقرأ من قائمة الانتظار هذه وتكتب إلى stdout في الأوقات المناسبة مع رسالتك السريعة.

لا أعتقد أن هذا ممكن. كيف يجب أن يتصرف ذلك على أي حال؟ لا شيء يظهر حتى يدخل المستخدم؟ إذا كان الأمر كذلك ، فلن يأتي الإخراج إلا عندما يصدر المستخدم أمرًا (أو أيًا كان نظامك) ، وهذا لا يبدو مرغوبًا فيه.

يجب أن يخرج المواضيع الخاصة بك إلى ملف آخر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top