필자가 최근 Python으로 필자 회사에서 사용중인 솔루션의 분석 결과를 별도로 추출할 수 있는 프로그램을 개발하고 있다. 사실 필자의 업무 영역에서 많이 벗어난 부분이지만, 시간은 부족하고 일은 많아지니 놀고 있는(?) 컴퓨터에게 필자 일을 조금 떠넘겨보려는 의도에서 만들고 있는 중이다.
지금 만드는 프로그램은 아무래도 고객사 내에서 사용되어야 하는 파일이기 때문에, 몇 가지 필수 조건이 존재한다. 첫 째로, window에서 돌아가야 하는 파일이어야 하며, 둘째로 python의 기본 모듈만 사용해야하며, 마지막으로 인가된 사용자만 이 프로그램을 사용하여 분석 결과를 확인할 수 있도록 하는 것이다. 너무도 당연한 이야기인데, 고객사 환경에는 python이 설치되어 있지 않을 확률이 높고, 설령 python이 깔려있더라도 별도 설치해야하는 패키지는 없을 확률 역시 매우 높고, 회사 내부의 분석결과가 아무에게나 보여져서는 안되기 때문이다.
따라서 프로그램 실행 시, 사용자를 인증할 수 있는 로그인 절차를 python의 기본 모듈로만 만들어야했는데 여기서 첫 번째 문제가 발생했다. Python에서 제공하는 비밀번호 입력을 위한 기본 모듈인 getpass의 경우, 키보드로 비밀번호를 입력하더라도 창에 입력되는 글자가 없기 때문에 아무래도 불편한 감이 있다(IT 기업에 제공되는 프로그램이라면 그냥 getpass를 쓰겠지만 그렇지가 않아서...)
이를 위해서는 키보드에서 입력받은 값을 화면에 곧바로 출력하기보다, 입력받은 값을 별도의 변수에 저장하고, 화면에 다른 기호(* 또는 #과 같은)가 출력되도록 만들어 줄 수 있어야 한다.
인터넷을 조금 뒤져보니, python 자체에서 키보드의 입력값을 한 글자씩 받을 수 있는 C언어의 getchar, 또는 한 글자씩 입력이 가능한 putchar와 같은 기능을 Python의 기본 모듈에서 제공하기는 한다. 이 모듈은 msvcrt 라는 이름의 모듈이다. 이번 포스팅에서는 msvcrt의 기본 함수(매서드)를 이용하여, 키보드 입력값 하나 하나를 제어하는 방법, 그리고 화면 출력과 커서 이동 등을 제어하는 방법에 대해 알아보려 한다.
* 비밀번호 입력 시, Asterisk(별표 *)가 나타나도록 코드를 작성하는 방법은 이곳을 참고하면 된다.
1. msvcrt 모듈
msvcrt는 이름에서도 대략적으로 유추할 수 있듯이 ms, 즉 윈도우와 상당히 연관이 깊은 Python 모듈이다. 이 모듈을 python.org 사이트의 documentation에서 확인하면 아래와 같은 내용이 나타난다.
조금 요약하자면, windows OS에서 유용하게 사용될 수 있는 기능을 msvcrt라는 모듈에 구현을 한 것인데, 내부의 함수(메서드)는 18개로 매우 적다. 그 중에서도 대부분이 콘솔의 입출력, 키보드 입력 및 화면 출력과 연관되어 있다.
당연하지만 window에 존재하는 기능을 가져다 쓰는 것이기 때문에, 리눅스에서 해당 모듈을 불러서 사용해봐야 의미가 없다.
2. msvcrt 모듈에서 키보드 입/출력값 확인
키보드의 입/출력값 하나 하나를 확인하는 함수는 get 또는 put 이라는 이름으로 시작한다. 함수의 종류로는 getch, getche, getwch, getwche, putch, putche, putwch, putche 등이 있지만, 함수마다 기능에서의 큰 차이를 보이지 않아서 기본적으로 사용하는 getch() 및 putch() 함수에 대해서만 설명을 진행하려 한다.
(1) msvcrt.getch()
msvcrt 모듈의 getch() 함수는 ASCII 코드로 입력된 키보드 값을 하나씩 화면에 출력해주는 함수다. msvcrt.getch() 코드를 작성하고 실행하면 마치 커서가 input() 함수를 사용했을 때와 같이 입력값을 기다리고 있는 것이 보인다. input() 함수와의 두 가지 차이점이 있는데, input() 함수는 반드시 enter 키로 개행문자가 입력되어야 종료되는데 반해, msvcrt.getch()는 어떠한 키보드 입력값이던지 한 글자만 입력되면 해당 글자를 출력하고 자동으로 종료된다는 점이 첫 번째고, 두 번째로 input()함수의 출력값이 문자열 형태임에 반해, msvcrt.getch()의 출력값은 binary 형태를 띈다는 점이다.
** 참고로 msvcrt.getwch()의 경우, 입력된 문자를 그대로 문자열 형태로 출력한다. 심지어 한글 자음/모음과 같은 Unicode 형태라도 말이다. 'ㄱ'에 대해서 msvcrt.getch()와 msvcrt.getwch() 결과를 비교해보면 알 수 있다.
만약, msvcrt.getch()로 여러 문자를 출력하고 싶다면 아래와 같이 for 문이나 또는 while 문과 같은 loop를 사용하는 것도 하나의 방법이다.
msvcrt.getch() 함수의 경우 Binary 형태로 출력값이 표시되다보니, 일반적으로 화면에 표시되지 않는 개행문자나 탭 문자 또는 Keyboard Interrupt(Ctrl +C)마저도 화면에 출력할 수 있다. 아래의 스크린샷은 코드 실행 후, 순차적으로 M, Ctrl+C, 백스페이스, 엔터, 탭을 입력한 결과이다.
이렇게 화면에 출력되지 않으나 Binary로 표시되는 문자들은 getch 객체 내에 존재하는 별도의 함수를 통해 문자열로 변환할 수 도 있다.
(2) msvcrt.putch()
msvcrt.getch() 함수가 키보드 입력값 하나에 대해 인식하는 함수라면, msvcrt.put() 함수는 반대로 화면에 출력되는 값을 인식하는 함수다. 따라서 이 함수의 경우, getch()와 달리 화면에 출력할 값을 인자로 사용해야 한다.
msvcrt.putch(바이너리 형태의 출력값)
위의 결과를 보면 알겠지만, 이 함수의 인자가 일반적인 문자 또는 문자열로 들어가거나, 인자가 없는 경우 Type에러가 발생한다. 더군다나 함수 이름에서도 유추할 수 있듯이 단 하나의 Binary 문자만 인식을 할 수 있게 되어 있기 때문에, 여러 문자를 입력하려면 다음과 같이 msvcrt.putch() 함수를 여러 번 입력해주어야 한다.
msvcrt.putch()의 경우, 커서의 이동도 제한된 범위 내에서 조작할 수 있다. 한다. 함수 인자로 b"\b" 를 입력하면 입력칸의 커서가 한 칸 뒤로 이동한다.
만약 입력한 글자 하나를 지우기를 원한다면 다음과 같이 코드를 작성해주어야 한다.
위의 코드가 의미하는 바는 다음과 같다. "커서를 하나 왼편으로 이동시키고 빈 값을 입력한 뒤, 빈 값 왼편으로 커서를 이동시킨다". 마지막 msvcrt.putch(b"\b")가 작동하기 전까지는 마치 insert 키에 의해 원래 입력되어 있던 값을 빈 값(Space)로 치환하는 것과 같은 효과를 나타낸다.
의외로 백스페이스를 의미하는 \x08의 경우, 실제 문자를 지우지 않고, \b와 동일한 효과를 내는데, 이 때문에 백스페이스 입력 시, msvcrt.putch(b"\x08")이 동작하도록 코드를 작성하더라도 커서만 왼편으로 이동할 뿐 글자가 지워지지 않음을 확인할 수 있다.
** msvcrt.getwch()와 마찬가지로 msvcrt.putwch() 함수도 msvcrt.putch()와 달리 Binary가 아닌 일반적인 문자열 형태로 인자를 사용할 수 있다.
Fin.
'Python > Python Advanced' 카테고리의 다른 글
10. Python - Lamdba의 활용 (0) | 2024.02.19 |
---|---|
9. Python - 자꾸 까먹어서 기록하는 Json, Yaml 파일 읽기/쓰기 (0) | 2023.08.11 |
7. Python - timeit모듈, timeit()매서드로 코드 실행시간 계산하기 (0) | 2021.05.12 |
6. Python - os 모듈: chdir(), listdir(), getcwd() 함수 (0) | 2020.08.17 |
5. Python - OS 모듈, system() 함수 (0) | 2020.07.01 |
댓글