Цветная подсказка Python в Windows?

Вот мой сценарий, который в настоящее время настраивает мои подсказки для всех моих компьютеров (будь то Windows, Red Hat или OS X):

import sys
import datetime
import platform

if platform.system() is 'Windows':
    tealUText   = ""
    tealText    = ""
    greenText   = ""
    defaultText = ""

else:
    tealUText   = "\001\033[4;36m\002"
    tealText    = "\001\033[0;36m\002"
    greenText   = "\001\033[0;32m\002"
    defaultText = "\001\033[0;0m\002"

class ClockPS1(object):
    def __repr__(self):
        now = datetime.datetime.now()
        clock = str(now.strftime("%H:%M:%S"))
        return tealUText + clock + greenText + " >>> " + defaultText

sys.ps1 = ClockPS1()
sys.ps2 = greenText + "         ... " + defaultText

Во всех системах это выводит текущее время, за которым следует обычное приглашение «>>>» в первой строке, а затем, если у меня есть многострочный ввод, у него есть обычное приглашение «...», но с отступом, чтобы он выравнивался с приглашение ">>>" (помните, что это приглашение начинается с текущего времени).

Вот вопрос: на всех платформах, кроме Windows, текущее время печатается бирюзовым (и подчеркнутым), подсказки зеленым, и все, что я печатаю, отображается обычным цветом. Как я могу добиться того же самого в Windows? Я видел несколько предложенных решений, но они основаны на вызове функций во время печати сообщения, что, я не думаю, сработает для меня из-за того факта, что переменные ps просто вызывают __repr__ для того, что им назначено, Правильно?

(Кстати, я получил этот временной трюк отсюда: python: отображать прошедшее время в оболочке )


person ArtOfWarfare    schedule 30.05.2014    source источник
comment
Не кодируйте экранирование цвета. Используйте модуль, например termcolor или colorama, который является более переносимым (домашняя страница colorama показывает, что он может работать в Windows, хотя не все свойства поддерживаются).   -  person Bakuriu    schedule 30.05.2014


Ответы (2)


На моей машине (Windows 7) Python запускается в «терминале» командной строки при выполнении, и, насколько мне известно, вы можете изменить цвет только для всего текста внутри этого терминала, так как весь текст будет одного цвета.

Я помню, как кто-то говорил о библиотеке под названием «clint», которая должна поддерживать терминалы MAC, Linux и Windows. Это означало бы добавить немного больше к вашему существующему сценарию.

person l0gic    schedule 30.05.2014
comment
Я совершенно готов добавить больше к моему сценарию. Я просто хочу, чтобы использование Python в Windows было таким же приятным, как и в других моих системах. - person ArtOfWarfare; 30.05.2014

Мне пришло в голову, что нет особой причины ограничивать себя только поиском текущего времени в моем классе PS1, и на самом деле, зачем возвращать текущее время как __repr__, когда вместо этого я мог бы просто распечатать время и подсказку в качестве побочного эффекта функции __repr__ и вместо этого вернуть пустую строку?

Поэтому я добавил следующий код (с добавлением надлежащих проверок платформы — я опускаю их, чтобы показать мясо и картошку, как заставить это работать в Windows):

from ctypes import *
# ... Skipped a lot of code which is the same as before...
STD_OUTPUT_HANDLE_ID = c_ulong(0xfffffff5)
windll.Kernel32.GetStdHandle.restype = c_ulong
std_output_hdl = windll.Kernel32.GetStdHandle(STD_OUTPUT_HANDLE_ID)
textText    = 11
greenText   = 10
defaultText = 15
class PS1(object):
    def __repr__(self):
        # ... Skipping a lot of code which is the same as before ...
        windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, tealText)
        sys.stdout.write(clock)
        windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, greenText)
        sys.stdout.write(" >>> ")
        windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, defaultText)
        return ""

Итак, теперь у меня часы бирюзового цвета, а подсказка зеленого цвета. Я хотел бы подчеркнуть, что ЭТО МНОГО РАБОТАЛО!

Я пытался сделать то же самое с PS2:

class PS2(object):
    def __repr__(self):
        windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, greenText)
        sys.stdout.write("         ... ")
        windll.Kernel32.SetConsoleTextAttribute(std_output_hdl, defaultText)
        return ""

ЭТО НЕ РАБОТАЕТ! Когда я попытался сделать это, я обнаружил, что интерпретатор мгновенно выводит PS1 и PS2 подряд, а затем не отображает PS2 в последующих строках. Казалось бы, обычно он получает все PS# __repr__ в самом начале и сохраняет результаты для последующего отображения. Но поскольку этот метод основан на побочных эффектах, он выставляется как хак, которым он и является.

Так что пока я придерживаюсь обычного " ... " вместо sys.ps2.

Я хотел бы услышать предложения о том, как сделать эти ... зелеными (без того, чтобы все, что я печатаю, было зеленым), но я подозреваю, что это может быть невозможно. Я буду рад принять любой ответ, который докажет, что я ошибаюсь - если в течение 2 дней он не придет, я, вероятно, просто приму этот ответ, пока кто-то другой не придумает что-то лучше.

person ArtOfWarfare    schedule 30.05.2014
comment
Сегодня я потратил некоторое время на изучение исходного кода Python. Он использует функцию C для преобразования sys.ps2 в строку C и сохраняет эту строку C до тех пор, пока она не будет использована PyOS_StdioReadline() — другой функцией C — для вывода подсказки пользователю (используя fprintf()). Таким образом, вы не можете взломать это, не изменив исходный код интерпретатора и не перестроив его. Слишком много работы для слишком мало пользы. - person ArtOfWarfare; 02.07.2014