الطباعة إلى ملف stdout وملف السجل أثناء إزالة رموز ألوان ANSI

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

سؤال

لدي الوظائف التالية لتلوين رسائل الشاشة الخاصة بي:

def error(string):
    return '\033[31;1m' + string + '\033[0m'

def standout(string):
    return '\033[34;1m' + string + '\033[0m'

أنا أستخدمها على النحو التالي:

print error('There was a problem with the program')
print "This is normal " + standout("and this stands out")

أرغب في تسجيل الإخراج إلى ملف (بالإضافة إلى stdout) بدون رموز ألوان ANSI ، نأمل دون الحاجة إلى إضافة خط "تسجيل" آخر إلى كل منهما print بيان.

السبب هو أنه إذا كنت ببساطة python program.py > out ثم الملف out سيكون لديك رموز ألوان ANSI ، والتي تبدو فظيعة إذا فتحت في محرر نص عادي.

اي نصيحه؟

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

المحلول

ال sys.stdout.isatty قد تكون الوظيفة قادرة على المساعدة:

from sys import stdout

def error(string, is_tty=stdout.isatty()):
    return ('\033[31;1m' + string + '\033[0m') if is_tty else string

def standout(string, is_tty=stdout.isatty()):
    return ('\033[34;1m' + string + '\033[0m') if is_tty else string

هذا في الواقع أحد الاستخدامات القليلة التي يمكنني التفكير فيها لاستخدام وسيطة افتراضية لم يتم ضبطها عليها None لأنه يتم تقييم الوسائط الافتراضية في وقت الترجمة في Python بدلاً من وقت التشغيل كما في C ++ ...

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

نصائح أخرى

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

import optparse
import logging

def error(string):
    return '\033[31;1m' + string + '\033[0m'

def standout(string):
    return '\033[34;1m' + string + '\033[0m'

def plain(string):
    return string.replace('\033[34;1m','').replace('\033[31;1m','').replace('\033[0m','')

if __name__=='__main__':
    logging.basicConfig(level=logging.DEBUG,
                        format='%(message)s',
                        filemode='w')
    logger=logging.getLogger(__name__)    
    def parse_options():    
        usage = 'usage: %prog [Options]'
        parser = optparse.OptionParser()
        parser.add_option('-l', '--logfile', dest='logfile', 
                          help='use log file')
        opt,args = parser.parse_args()
        return opt,args
    opt,args=parse_options()
    if opt.logfile:
        class MyFormatter(logging.Formatter):
            def format(self,record):
                return plain(record.msg)
        fh = logging.FileHandler(opt.logfile)
        fh.setLevel(logging.INFO)
        formatter = MyFormatter('%(message)s')
        fh.setFormatter(formatter)
        logging.getLogger('').addHandler(fh)

    logger.info(error('There was a problem with the program'))
    logger.info("This is normal " + standout("and this stands out"))

test.py يطبع فقط إلى المحطة.

test.py -l test.out يطبع على كل من المحطة والملف test.out.

في جميع الحالات ، يحتوي النص على المحطة على رموز ألوان ، في حين أن التسجيل يحتوي على أي شيء.

إجابة Unubtu أدناه رائعة ، لكنني أعتقد أن MyFormatter يحتاج إلى تعديل بسيط لفرض التنسيق في طريقة التنسيق ()

class MyFormatter(logging.Formatter):
        def format(self,record):
            msg = super(MyFormatter, self).format(record)
            return plain(msg)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top