'콘솔'에 해당되는 글 1건

  1. 2014.05.28 [파이썬] 터미널에서 컬러 텍스트 출력하기



터미널용 유틸리티를 개발하다 보면 출력 메시지에 색상을 부여하여 가독성을 높이고 싶을 때가 있다.

예를 들어 오류가 발생했다면 빨간색 텍스트로 표시한다거나 경고 문구는 노란색 텍스트로 표시하는 것이다.

파이썬으로 유틸리티를 개발할 경우 ColorConsole 모듈을 사용하면 된다.

https://code.google.com/p/colorconsole/

물론 이 외에도 다양한 모듈들이 존재하지만, 윈도우와 유닉스를 모두 지원하는 모듈을 찾지 못했다.

터미널에서 색상 문자열을 출력하는 방법은 플랫폼마다 다르다.

POSIX시스템에서는 아주아주 쉽다. 그냥 ANSI코드를 사용하면 된다.(예: "\x1b[30m".. 이야기에서 안시코드가지고 놀던 기억이....새록새록.)

그러나 윈도우 command prompt의 경우 별도 WINAPI를 호출해야 한다.(쩝..MS Command Prompt는 안시코드를 지원하지 않는다. 마치 디렉토리 구분자를 '\'로 만든 것과 동일하다. 이로 인한 클로스플랫폼 개발이 얼마나 사소하게 어그러졌는지원...쩝. 아니면 ANSI출력을 지원하는 command prompt 대체 프로그램을 사용해야 한다.)


colorconsole 모듈에서 제공하는 예제도 깔끔하고, 특정 위치 출력같은 부가기능도 사용할 수 있으므로, 다음 문서 페이지를 참고하자.

https://code.google.com/p/colorconsole/wiki/PageName?tm=6


자세한 설명을 생략한다. 다만 해당 모듈의 소스코드에서 배울 만한 스타일에 대해서만 살짝 살펴보자.



Source: https://flic.kr/p/7ucxPT


일단 terminal.py의 get_terminal() 함수부터 보자. 이 함수는 os.name에 따라 필요한 모듈을 import한 다음, 터미널 인스턴스를 생성하여 반환한다. 즉, import module을 반드시 스크립트 시작부분에서만 사용할 수 있는 것은 아니다.

def get_terminal():
    if os.name == "nt":
        import colorconsole.win        
        return colorconsole.win.Terminal()
    if os.name == "posix":
        import colorconsole.ansi       
        return colorconsole.ansi.Terminal()
    else:
        return None # Should raise exception!


win.py모듈에서 눈에 띄는 코드 부분은 WIN32API를 호출하는 방식이다.


# Window에서 런타임이 지원하는 API 호출시 필요.
import msvcrt  
# DLL 함수 및 구조체.
from ctypes import windll, Structure 

# C처럼 구조체를 사용하기.
class COORD(Structure): 
  """struct in wincon.h."""
  _fields_ = [
    ("X", SHORT),
    ("Y", SHORT)]

# 구조체를 사용하는 방법도 C와 비슷하다.
# pt = COORD(1, 2)
# pt.x = 2

# kernel32.dll의 함수를 호출할 때 그냥 짧은 함수이름으로 alias시켜준다.
# 콘솔과 관련된 함수는 다음 웹사이트를 참고하자.
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073(v=vs.85).aspx
SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute

class Terminal:
    # 클래스내에서 사용하는 상수는 다음과 같이 정의한다.
    STD_INPUT_HANDLE = -10
    STD_OUTPUT_HANDLE = -11

    def __init__(self):
        # 표준 입출력의 핸들은 다음과 같이 구할 수 있다.
        # 예상대로 표준 오류 핸들은 -12이다. 
        # http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231(v=vs.85).aspx
        self.stdout_handle = windll.kernel32.GetStdHandle(Terminal.STD_OUTPUT_HANDLE)
        self.stdin_handle = windll.kernel32.GetStdHandle(Terminal.STD_INPUT_HANDLE)

참고로 만약 파이프로 리다이렉션되었는지를 감지하는 방법은 있을까?

sys.stdout.isatty()를 호출하여 True인지 False인지를 보고 실제 콘솔 출력인지 파이프로의 출력인지를 알 수 있다.



Posted by NeoZest