블로그 이미지
자유로운설탕

calendar

1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

Notice

2017. 2. 26. 20:00 프로그래밍

  7교시는 엑셀을 다루는 부분에 대해서 얘기하려고 한다. 보통 프로그램에서 나온 결과를 텍스트나 디비로 많이 저장하지만, 엑셀로 저장하게 되면, 여러가지 엑셀의 기능을 이용해서 정렬해 보기도 쉽기 때문에, 나름 장점이 있는 듯 한다.

 

[목차]

0. 왜 파이썬 공부에 구글을 이용하는게 좋은가?

1. 언어를 바라보는 방법. 파이썬을 어떻게 바라봐야 할까?

2. 파이썬 설치와 환경, 버전 선택 하기의 이유.

3. 만들고자 하는 기능을 모르는 조각으로 나눠 조사해 보기

4. 데이터 베이스에서 내용 가져와 출력하기

5. 암호화 모듈을 이용해 암복호화 해보기

6. 퍼즐 조각들을 합쳐보기

7. 엑셀 파일 사용해 보기 -> 부록 : fuction 을 이용해서, 코드 정리해 보기

8. 정규표현식을 왜 사용해야 할까? 언어속의 미니 언어 정규표현식 살펴보기

9. 입력과 결과를 GUI 화면과 연결해 보기

10. Whois API 이용해 보기

11. 웹페이지 호출해 내용 파싱 하기(BeautifulSoup 그리고 한계)

12. 자동화 - 웹 자동화(with Selenium)

13. 자동화 - 윈도우즈 GUI 자동화(with pywinauto)

14. 자동화 - 작업 자동화

15. 수학 라이브러리 살펴보기

16. 그래픽 라이브러리 살펴보기

17. 머신러닝에서의 파이썬의 역활

18. 웹 프로그래밍 - Legacy Web

19. 웹 프로그래밍 - Flask 살펴보기(feat. d3.js)

20. 웹 프로그래밍 - Django 살펴보기

21. 정리 - 이런저런 이야기

 

 

 

[엑셀 모듈 설치]

  언제나처럼 구글에 검색을 시작한다. 'python 3 excel' 라고 검색하면, 제일 위의 결과에 파이썬에서 쓸수 있는 엑셀 모듈들에 대해 정리한 사이트가 나온다.

http://www.python-excel.org/

 

  쭈루룩 5개정도의 모듈이 나오는데, 맨 위에 있는 OpenPyXl 을 써보기로 하자. 모듈을 설치하기 위해서 구글에서 'install openpyxl python3 pip' 로 검색하여 아래의 스택오버플로우 페이지를 참고한다.

http://stackoverflow.com/questions/38364404/how-to-install-openpyxl-with-pip

 

  cmd 창에서 'pip install openpyxl' 를 실행 한다. 특별한 이슈 없이 잘 설치 된다~

c:\Python\code>pip install openpyxl
....
Installing collected packages: openpyxl
  Running setup.py install for openpyxl ... done
Successfully installed openpyxl-2.4.4

 

 

 

 

[샘플 동작 검증]

  그럼 일단 모듈이 잘 돌아간 다는 것을 테스트 하기 위해서 샘플 파일을 찾아본다. 구글에서 'python openpyxl sample' 로 찾으면 첫 페이지 중간 쯤에 아래와 같은 샘플 링크가 있다.

  https://pypi.python.org/pypi/openpyxl

 

  그냥 돌려도 잘 돌아가지만 내용 중 일부가 먼저 쓴 값을 덮는 식으로 만들어져 있어서 한글 주석도 달겸 셀이 겹치지 않도록 일부 수정해 본다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from openpyxl import Workbook
import datetime
 
# 워크북 하나 만들기
wb = Workbook()
 
# 활성 워크시트 선택 하기(뭐 첫번째 것이 선택 된다) 
ws = wb.active
 
# A1 행에 42라는 숫자를 넣는다.
ws['A1'= 42
 
# 현재 글자가 쓰여있는 다음 row 에 1,2,3 이라고 넣는다.
ws.append([123])
 
# 요 부분을 바꿈 A2 로 하면 1,2,3 중 1이 겹쳐 쓰여져서, A3로 수정
ws['A3'= datetime.datetime.now()
 
# 메모리에 있는 워크 북을 실제 엑셀 파일로 저장해 형상화 한다.
wb.save("sample.xlsx")
cs

 

 

 워크 북(workbook), 워크 시크(work sheet)라는 조금 낯설은 용어가 나오지만, 우리가 평소 보는 엑셀을 기준으로 비교해 보면 아주 간단한다. 아래의 그림만 이해한다면 작업은 단순한 인형눈 끼우는 알바 모드가 된다. 엑셀의 표들이 있는 가장 바깥 쪽 부분이 workbook 이며, 엑셀 문서 하나 하나를 얘기한다고 봐도 무방할 듯 하다. 그 안에 들어있는 탭 문서들이 work sheet 이다.

   

  c:\python\code 에 위의 소스 파일을 가져다 excel_sample.py 이름으로 저장하여 실행 한다. (저장하고 실행하는 부분을 모르겠으면 자세히 설명한 2교시에서 보고 오길 바란다.)

c:\Python\code>python excel_sample.py

 

  코드를 실행 시키면 화면엔 아무것도 안 출력 되지만 폴더 안을 보면 아래와 같이 우리가 만든 코드가 실행 되어 sample.xlsx 파일이 만들어져 있다(참고로 테스트를 위해 여러번 실행 할 때, sample.xlsx 엑셀 파일을 열어 놓은 상태면 쓰지 못해서 에러가 난다). 파이썬 코드와 만들어진 값의 상관 관계를 결과 값 그림에 표시해 본다.

 

 

 

 

[문제 나누기 - 컬럼이름 얻어오기]

  그럼 샘플은 실행해 검증해 봤고, 이제 우리가 원하는 기능을 만들어 보려고 한다.  4교시 때 우리가 만들어 보았던 supermarket 테이블을 조회한 내용을 엑셀에 저장해 보려 한다. 그런데 단순히 내용만 저장하면 거의 기존 수업 반복이여서 재미가 덜 하니까. 컬럼 이름을 얻어와서 엑셀의 맨 첫 번째 라인에는 컬럼 명을 적어 좀더 보기 좋게 하려 한다.

 

  어 그럼 테이블의 컬럼 이름을 어떻게 얻어와야 하지? 하는 문제가 생긴다. 구글에서 'mssql table column name' 이라고 검색한다. 제일 첫번째 문서인 아래 문서의 링크를 열어보면, 여러개의 설명들이 있는데, 제일 심플해 보이는 아래 코드를 선택한다. 테이블의 스키마 구조를 저장하고 있는 테이블에서 컬럼이 이름을 가져오는 쿼리이다.

http://stackoverflow.com/questions/1054984/how-can-i-get-column-names-from-a-table-in-sql-server

 

SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.
COLUMNS
WHERE TABLE_NAME = 'name_of_your_table'

 

 

  그럼 저 쿼리안의 'name_of_your_table' 안에 4교시에 만든 'supermarket' 으로 바꾸어서, 잘 돌아가나 검증을 위해 쿼리 분석기에서 실행해 본다. (쿼리 실행 부분을 잘 모르겠으면, 4교시에 자세히 설명했으니 가서 보고 온다).  실행해 보면 우리가 원하는 컬럼 값이 잘 나옴을 볼수 있다.

 

 

 

[문제 나누기 - 루프를 이용해 엑셀에 출력하기]

   또 하나의 해결해야할 부분은 엑셀에 뿌려주는 문제이다. 디비 구조하고 엑셀 구조는 상당히 비슷하기 때문에, 디비를 한줄 읽어서 컬럼 들을 가로로 쭉 써주고, 또 한줄 읽어서 가로로 쭉 써주는 걸 반복하면 되는데, 행이 증가 하는건, 아래 그림과 같이 뒤의 숫자만 1, 2, 3 으로 증가 시켜줌 되는데, 가로로 증가하는건 뒤의 숫자가 고정된 채 문자가 하나씩(A, B, C) 늘어나야 한다. 말로 표현해 보면,"DB의 첫째 행을 가져와 A1~E1 에 저장하고, 다음 행을 가져와 A2~E5 에 저장해야 한다."

 

  for 문을 2개 겹쳐 써야 한다고 대충 감은 든다. 안쪽 for 문은 A1~E1 식으로 숫자는 고정한 채 알파벳만 늘어나게 해주어 한줄을 표시 하는 기능을 하고, 바깥 쪽 for 문은 뒤의 숫자를 하나 증가해 줄을 바꾸어 주어, 다음번 안쪽 for 문이 A2~E2 식으로 다음 줄에 표시하게 해줌 된다. 

 

  그런데 숫자 증가하는건 i = i + 1 하면 될거 같은데,  문자를 어떻게 증가 시킬 지 모르겠다(아스키 코드 어쩌고 하는 식으로 내부적으로 문자가 숫자로 됬다는건 기억이 나긴 한다). 그럼 다른 사람이 문자 증가 문제를 해결한 코드를 찾기 위해 'python increase alphabet' 으로 구글을 조회한다. 위에서 두번째 결과인 아래 페이지를 보면, char = chr(ord(char) + 1) 라는 코드를 알려준다. ord 가 뭘 하는 건지 'python ord' 로 찾아 해석해 보면 ord 는 문자를 아스키 코드로 바꿔주는 함수이기 때문에, 해당 코드는 '문자를 아스키 코드로 변경하여 1을 더하고, 다시 문자로 바꿔준다' 의 기능을 한다.

http://stackoverflow.com/questions/11827226/can-we-increase-a-lowercase-character-by-one

 

 

  그럼 해당 코드를 이용하여 첫 번째 컬럼 명을 출력하는 부분은 아래와 같이 만들어 질 수 있다. (한 행만 찍음 되기 때문에 바깥 쪽 루프는 없어도 된다. 안에 보면 '1' 로 하드코딩 되있다) 

1
2
3
4
5
6
7
8
9
10
11
12
# 컬럼 1번째 표시
column_char = 'a'
# supermarket 의 컬럼들 가져옴
cursor.execute('SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = \'supermarket\';')
 
# 한행 씩 가져오면서
row = cursor.fetchone()
while row:
# 컬럼 문자를 하나씩 증가하면서 해당 행을 넣음.
  ws[column_char + '1'= row[0]
  column_char = chr(ord(column_char) + 1)
  row = cursor.fetchone()
cs

 

  위의 코드가 돌아가면 A1 = row[0](첫번째 컬럼이름), B1 = row[0](두번째 컬럼이름)... 이런식으로 엑셀의 맨 첫줄에 다섯 개의 컬럼 이름이 들어간다.

 

 

  두번 째는 내용을 출력 하는 코드 부분이다. 비슷하지만, 조회된 내용을 한 줄씩 가져오며 내용이 없을 때까지 루프를 돌리는 while 문이 바깥쪽 for 루프 역활을 한다. 아까 구상 했듯이 안쪽 for 문이 한 행(5개 컬럼)을 출력하는 역활을 한다. 처음 1행은 컬럼 이름이 들어가 있을 것이므로, column_num 을 2로 해서 2번째 행부터 내용이 출력되게 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2번째 행 표시
column_num = 2
# supermarket 테이블의 내용을 가져온다.
cursor.execute('SELECT Itemno, Category, FoodName, Company, Price FROM supermarket(nolock);')
 
# 한 행씩 가져오면서
row = cursor.fetchone()
while row:
# 예전 수동 타자기 처럼, 새로운 줄이 오게 되면, 첫째 셀 a 로 돌아가는 초기 값
  column_char = 'a' 
# 1~5 까지 x 가 변하면서 컬럼 문자, row를 하나씩 늘여 결과를 하나씩 담음. 
# ws['a1'] = row[0], ws['b1'] = row[1], ws['c1'] = row[2]...
  for x in range(16):
    ws[column_char + str(column_num)] = row[x-1]
    column_char = chr(ord(column_char) + 1)
 
# 다음 행을 표시하기 위해 뒤의 숫자 증가       
  column_num = column_num + 1
  row = cursor.fetchone()
cs

 

 

 

 

[해결된 조각 합치기]

  그럼 위의 코드들을 모두 적절히 합치면 아래와 같은 전체 소스가 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#-*- coding: utf-8 -*-
from openpyxl import Workbook
from openpyxl import load_workbook
#from openpyxl.compat import range
import pymssql
 
wb = Workbook()
 
# grab the active worksheet
ws = wb.active
ws.title = "output"
 
conn = pymssql.connect(server='localhost', user='pyuser', password='test1234', database='mytest')
cursor = conn.cursor()
 
 
column_char = 'a'
# supermarket 의 컬럼들 가져옴
cursor.execute('SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = \'supermarket\';')
 
# 한행 씩 가져오면서
row = cursor.fetchone()
while row:
# 컬럼 문자를 하나씩 증가하면서 해당 행을 넣음.
  ws[column_char + '1'= row[0]
  column_char = chr(ord(column_char) + 1)
  row = cursor.fetchone()
 
 
# 2번째 행 표시
column_num = 2
# supermarket 테이블의 내용을 가져온다.
cursor.execute('SELECT Itemno, Category, FoodName, Company, Price FROM supermarket(nolock);')
 
# 한 행씩 가져오면서
row = cursor.fetchone()
while row:
# 예전 수동 타자기 처럼, 새로운 줄이 오게 되면, 첫째 셀 a 로 돌아가는 초기 값
  column_char = 'a' 
# 1~5 까지 x 가 변하면서 컬럼 문자, row를 하나씩 늘여 결과를 하나씩 담음. 
# ws['a1'] = row[0], ws['b1'] = row[1], ws['c1'] = row[2]...
  for x in range(16):
    ws[column_char + str(column_num)] = row[x-1]
    column_char = chr(ord(column_char) + 1)
 
# 다음 행을 표시하기 위해 뒤의 숫자 증가       
  column_num = column_num + 1
  row = cursor.fetchone()
 
# 파일을 실제 저장
wb.save("test.xlsx")
cs

 

  excel_save.py 로 저장하고 실행 하면 아래와 같이 test.xlsx 파일이 만들어 진다.

c:\Python\code>python excel_save.py

 

 

  역시 실행 결과는 안보이지만, test.xlsx 엑셀 파일을 열어보면 아래와 같이 컬럼명과 내용들이 들어가 있다.

 

 

 

[역지사지 - 엑셀 읽어오기]

  마지막으로 저장의 반대인 읽어오기도 위의 식으로 비슷하게 루프를 돌리면서 가져오고 싶은 값을 지정 하면 될 것이다. 쓰기가 충분히 해당 루프를 돌리는 방식을 구현하는 부분을 해결했다고 생각하기 때문에 여기서는 간단하게 읽어와서  A1(Itemno), B2(과자) 값을 출력하는 예제만 봐보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#-*- coding: utf-8 -*-
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.compat import range
import pymssql
 
# 엑셀을 읽어와
wbread = load_workbook(filename = 'test.xlsx')
 
# 이름이 output 인 sheet 를 가져온다.
mysheet = wbread['output']
 
# a1, a2 값을 출력한다
print (mysheet['a1'].value + ' ' + mysheet['b2'].value)
cs

 

  excel_read,py로 저장하고 실행을 하면, 아래와 같이 결과가 나온다.

c:\Python\code>python excel_read.py
Itemno 과자

 

 

 

[마치면서...]

  처음 찾았던 엑셀 모듈 모아놓은 사이트에서 소개했던 openpyxl 외의 다른 모듈의 샘플을 보니 셀을 지정할때, A1, A2 식으로 안하고, (1,1) (1,2) 식으로 좌표식으로 표시하는 모듈도 있다. 인기 많고 유지보수 되는 모듈 중, 각자 쓰기 편하다고 생각되는 모듈을 사용하면 될 듯하다.

 

  그리고 이제와 고백하자면 위의 코드엔 알고도 놔둔 버그가 있다. 아스키 코드를 증가시키는 방법은 A, Z 까지 밖에 안되는데, 엑셀의 가로행은 Z 까지 가면 AA 같이 두자리로 늘어나고 ZZ 담에는 세자리로 늘어난다. 그럼 사실 저 부분도 그 부분을 고려해야 하는데, 테이블 컬럼이 26개(a-z) 이상은 잘 안 쓰일거 같아서 그냥 두었다. 뭐 개인적으로 파이썬은 유틸리티 방식으로 사용하는 편이라서, 26개 이상 필요가 생기면 고치려 했다고 변명 하고 싶다 --; (가로 문자를 증가시키는 로직을 만들던지 위의 좌표 지정 방식의 모듈을 사용해 숫자로만 루프를 돌리는 것도 하나의 해결 방법일 듯 싶다.)

 

  그럼 다음 시간인 '7교시 부록'에서는 살짝 문법 시간으로 가서, 지금 만든 스크립트 샘플을 함수를 이용해 (자신은 별로 없지만) 정리하는 부분을 살펴 보면서 구조화된 코드에 대해 잠시 생각하는 시간을 가져 보려고 한다.

 

 

 

[보충 #1]

  최근 어떤 책을 보다가 발견한건데, openpyxl 에서도 위에 같이 ws['a1'].value 같이 문자 말고,

ws.cell(row=1, column=2).value 로 하는것도 가능하다--; 뭐 위의 코드도 억지로 돌아가긴 하지만, 괜히 어려운 길을 간거 같아서 조금 미안하다^^. 관심 있으신 분은 위의 코드를 아래와 같이 row, column 지정 방식의 코드로 조금만 수정하면 코드가 더 간략해 질것 같다. 숫자로 지정하는 샘플 코드만 아래에 추가 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#-*- coding: utf-8 -*-
from openpyxl import Workbook
wb = Workbook()
 
# grab the active worksheet
ws = wb.active
 
# 예제로 들었던 방식
ws['A1'= 12
 
# 더 편한 방식
ws.cell(row=2, column=2).value = 777 
 
# Save the file
wb.save("sample.xlsx")
cs

 

추가 -> 댓글에서 SSL 이 알려주셔서..

2.5버전 부터는 아래와 같이 값을 바로 넣어도 되네요.

ws.cell(row=2, column=2).value = 777

 

 

[보충 #2]

  문의가 와서 보니 openpyxl 최신버전에서는 아래 import 문이 에러가 나네요. 지금 보니 사실상 코드안에서 사용하지 않는 부분이라서 아예 빼버림 에러가 발생안합니다

from openpyxl.compat import range

 

 

2017.2.28 by 자유로운설탕
cs

 

 

 

posted by 자유로운설탕
2017. 2. 25. 21:55 프로그래밍

  이젠 4교시 때 정리한 mssql 코드와 5교시 때 정리한 암호화 코드를 이용해서 최종 기능을 만들어 보자.

 

[목차]

0. 왜 파이썬 공부에 구글을 이용하는게 좋은가?

1. 언어를 바라보는 방법. 파이썬을 어떻게 바라봐야 할까?

2. 파이썬 설치와 환경, 버전 선택 하기의 이유.

3. 만들고자 하는 기능을 모르는 조각으로 나눠 조사해 보기

4. 데이터 베이스에서 내용 가져와 출력하기

5. 암호화 모듈을 이용해 암복호화 해보기

6. 퍼즐 조각들을 합쳐보기

7. 엑셀 파일 사용해 보기 -> 부록 : fuction 을 이용해서, 코드 정리해 보기

8. 정규표현식을 왜 사용해야 할까? 언어속의 미니 언어 정규표현식 살펴보기

9. 입력과 결과를 GUI 화면과 연결해 보기

10. Whois API 이용해 보기

11. 웹페이지 호출해 내용 파싱 하기(BeautifulSoup 그리고 한계)

12. 자동화 - 웹 자동화(with Selenium)

13. 자동화 - 윈도우즈 GUI 자동화(with pywinauto)

14. 자동화 - 작업 자동화

15. 수학 라이브러리 살펴보기

16. 그래픽 라이브러리 살펴보기

17. 머신러닝에서의 파이썬의 역활

18. 웹 프로그래밍 - Legacy Web

19. 웹 프로그래밍 - Flask 살펴보기(feat. d3.js)

20. 웹 프로그래밍 - Django 살펴보기

21. 정리 - 이런저런 이야기

 

 

 

[들어가면서]

  최종 기능은 테이블에 저장된 평문 문자열을 암호화 한 후 복호화 해서 각각 테이블 내 다른 필드에 저장하고, 이후 전체 내용을 조회해 잘 암,복호화 됬다는 증거로 화면에 표시한다. 그림으로 표시하면 아래와 같다.

 

 

 

[테이블과 원본 데이터 생성]

  일단 테이블을 하나 만든다. 4교시때 만든 'mytest' db에 저장하고, 만약 테이블 생성 하는 부분이 가물가물 하다면, 4교시에 자세하게 설명해 놓았으니 참고하여 생성한다.

1
2
3
4
5
CREATE TABLE [dbo].[play](
    [original] [char](30) NULL,
    [encrypted] [char](200) NULL,
    [decrypted] [char](30) NULL,
)
cs

 

  이후 위의 그림의 A 값을 하나 넣는다.

1
insert play values('secret','','')
cs

 

  내용을 한번 조회해 본다.

1
select * from play(nolock)
cs

 

  아래와 같이 original 에만 우리가 넣은 secret 라는 단어가 들어가 있다. 나머지 2개는 파이썬이 채워줄 예정이다.

 

 

 

[업데이트 쿼리 만들기]

  4, 5교시때 진행한 내용을 되돌아 보면 현재 우리가 모르고 있는 부분 하나는 테이블의 encrypted, decrypted 필드에 원하는 값을 업데이트를 하는 것이다. DB는 복잡하게 보면 많이 복잡하지만 단순하게 보면 파일과 비슷한 면이 있다.(사실 DB는 파일에 저장하는 것을 좀 더 구조적으로 저장하여, 상호 관계를 분석하거나 빠르게 결과를 찾기 위해 만들어진 구조화된 파일 이라고 봐도 될 듯하다.) 파일에 할수 있는 일이 생성(create), 수정(update), 내용, 파일 삭제(delete), 읽기(read) 이 듯, DB안에 들어가 있는 테이블에 할 수 있는 작업도 역시 이 4가지다. 그래서 좀 이 4개의 행동들의 앞 자리들을 따서 조금 고상하게 CRUD 라고 표현하기도 한다. 그럼 4교시때 select 하는 부분은 배웠는데, update 하는 내용은 배우지 않았으니 update 하는 부분을 구글을 통해 찾아보려 한다.

 

  구글에서  'mssql update' 로 검색한다. 한글로 잘 정리된 페이지를 참조해도 좋고, 이전 시간에도 참고했던 아래 techonthenet 페이지를 보자(개인적으로 깔끔하게 핵심만 정리한듯 하여...)

https://www.techonthenet.com/sql_server/update.php

 

  간단히 설명하면 아래와 같다.

1
2
3
4
5
6
UPDATE 테이블
SET 컬럼1 = '값1',
    컬럼2 = '값2' ....
WHERE 컬럼x = '값3';
-- 테이블을 업데이트 하는데, 특정 컬럼에 값3이 들어있는 행을 찾아서, 
-- 컬럼1,2를 새로운 값으로 채운다.
cs

 

  해당 문법을 참조하여 좀 전에 만든 테이블 구조를 업데이트 하는 쿼리를 만들면 아래와 같다.

1
2
3
4
5
-- secret 가 저장된 행을 찾아서 encrypted 컬럼을 암호화된 값으로 업데이트 한다.
update play set encrypted = '암호화 값' where original='secret'
 
-- secret 가 저장된 행을 찾아서 decrypted 컬럼을 복호화된 값으로 업데이트 한다.
update play set decrypted = '복호화 값' where original='secret'
cs

 

 

  해당 코드를 이전 시간의 암호화 한 함수 코드를 호출하는 방식으로 만들면 아래와 같이 된다.

1
2
3
4
5
6
7
8
9
10
# original 필드 조회한다
cursor.execute('SELECT original FROM play(nolock);')
row = cursor.fetchone()
original = str(row[0])
# 암호화 한다.
encrypted = AESCipher(key).encrypt(original)
 
# 암호화한 값 encrypted 필드에 업데이트 한다.
cursor.execute("update play set encrypted = %s where original='secret'", encrypted)
conn.commit()
cs

 

 

  해당 코드를 복호화 한 함수를 호출하는 방식으로 합쳐서 만들면 아래와 같이 된다.

1
2
3
4
5
6
7
8
9
10
# encrypted 필드 조회한다
cursor.execute('SELECT encrypted FROM play(nolock);')
row = cursor.fetchone()
encrypted_select = str(row[0])
# 복호화 한다
decrypted_insert = AESCipher(key).decrypt(encrypted_select)
 
# 복호화 한 값 decrypted 필드에 업데이트 한다.
cursor.execute("update play set decrypted = %s where original='secret'", decrypted_insert)
conn.commit()
cs

 

 

  전체를 조회하는 쿼리는 SQL 샘플과 비슷하지만, 줄 바꿈을 위해 약간 보기 좋게 하기 위해서 문자열 더하기 연산자와(+), 문자열 좌우의 빈 공간을 지우는 함수(strip)를 이용하여 보기좋게 정렬하려 한다. 해당 코드는 아래와 같다.

1
2
3
4
5
6
7
# 모두 조회해서 줄로 나누어('\n') 출력한다. strip() 함수는 양쪽의 공백을 없애준다.
cursor.execute('SELECT * FROM play(nolock);')
row = cursor.fetchone()
while row:
  print ('original  : ' + str(row[0]) + "\n" + 'encrypted : ' 
  + str(row[1]).strip() + "\n" + 'decrypted : ' + str(row[2]))   
  row = cursor.fetchone()
cs

 

 

 

[전체 코드 조합하기]

  그럼 좀 길어 지지만 앞의 암복호화 함수와 합치게 되면 아래와 같이 된다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#-*- coding: utf-8 -*-
# 암호화 코드 출처: http://blog.dokenzy.com/
 
import pymssql
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
 
# 아마 특정한 블록 사이즈를 채우기 위해서 입력된 값을 임의의 값으로 패딩(채워주기) 하는 코드 인 듯...
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode()
unpad = lambda s: s[:-ord(s[len(s)-1:])]
 
# 초기화 코드 인듯
def iv():
    return chr(0* 16
 
# 2교시때 설명했 듯이 클래스는 구조를 잘 잡아주는 껍데기 이다.
class AESCipher(object):
 
    def __init__(self, key):
        self.key = key
 
    # 메시지를 암호화 하는 함수 
    def encrypt(self, message):
        message = message.encode()
        raw = pad(message)
        cipher = AES.new(self.key, AES.MODE_CBC, iv())
        enc = cipher.encrypt(raw)
        return base64.b64encode(enc).decode('utf-8')
    
    # 메시지를 복호화 하는 함수
    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        cipher = AES.new(self.key, AES.MODE_CBC, iv())
        dec = cipher.decrypt(enc)
        return unpad(dec).decode('utf-8')
 
# 암호화 키 
key = 'abcdefghijklmnopqrstuvwxyz123456'
 
 
# 커넥션 만들기
conn = pymssql.connect(server='localhost', user='pyuser', password='test1234', database='mytest')
cursor = conn.cursor()
 
# original 필드 조회한다
cursor.execute('SELECT original FROM play(nolock);')
row = cursor.fetchone()
original = str(row[0])
# 암호화 한다.
encrypted = AESCipher(key).encrypt(original)
 
# 암호화한 값 encrypted 필드에 업데이트 하기
cursor.execute("update play set encrypted = %s where original='secret'", encrypted)
conn.commit()
 
# encrypted 필드 조회한다
cursor.execute('SELECT encrypted FROM play(nolock);')
row = cursor.fetchone()
encrypted_select = str(row[0])
# 복호화 한다
decrypted_insert = AESCipher(key).decrypt(encrypted_select)
 
# 복호화 한 값 decrypted 필드에 업데이트 하기
cursor.execute("update play set decrypted = %s where original='secret'", decrypted_insert)
conn.commit()
 
# 모두 조회해서 줄로 나누어('\n') 출력한다. strip() 함수는 양쪽의 공백을 없애준다.
cursor.execute('SELECT * FROM play(nolock);')
row = cursor.fetchone()
while row:
  print ('original  : ' + str(row[0]) + "\n" + 'encrypted : ' 
  + str(row[1]).strip() + "\n" + 'decrypted : ' + str(row[2]))   
  row = cursor.fetchone()
cs

 

  위의 최종 소스를 긁어 c:\python\code 디렉토리에 mix_version.py 라고 파일을 만들고 실행 한다. (역시 실행 방법을 잘 모르겠으면 2교시를 참고한다). 아래와 같이 DB 에 저장 후 필드를 읽어와 화면에 가지런히 표시된다.

c:\Python\code>python mix_version.py
original  : secret
encrypted : F8/7UoVxGVoOxNdlo/0sbf/whobfIAoSVe3QvcbgehI=
decrypted : secret

 

 

 

[디버깅 및 리셋]

  직접 만들어 보는 경우는 중간 중간에 print 문을 통해 변수를 출력하여(물론 리스트와 같은 복합 자료형은 원하는 값을 출력하는 방법에 익숙해야 한다) 해당 값이 정확히 나오는지 확인 해 보는 것이 좋다. 아니면 pycharm 같은 IDE 툴의 디버깅 기능을 이용해도 될 듯 하다. 구글에서 'pycharm 디버깅' 이라고 치면 많은 블로그가 나온다. (뭐 하지만 여러 디버깅 책 들에서 얘기하듯이 디버깅은 머리속으로 구조적으로 하는 거고, print 나 디버깅 기능은 생각한 가설이 맞는지 실제 검증 할때 쓰는 것이라는 것을 잊으면 안된다). 테스트 도중 값을 리셋하기 위해 쓸 수 있는 쿼리를 아래 명시 하였다.(original 값만 빼고 나머지 두 값을 지워준다)

1
2
update play set encrypted ='', decrypted = ''
where original = 'secret'
cs

 

 

 

 

[Database 타입에 대한  간략 브리핑]

  마무리 하기 전에 앞 시간에서 여기서 정리한다고 했으니 database 에 대해 잘 모르는 사람들을 위해 요즘 회자되고 있는 여러가지 database 에 대해서 희미하게 아는 지식으로 간단히 분류하려 한다. 보통 많이 듣는 DB가 관계형 디비인 oracle, mssql, mysql, mariadb, postgreSQL, 빅데이터 라고 부르는 hBase, hive 등, 위치가 조금은 애매한 도큐먼트 디비인 mongodb, 그리고 메모리 디비라고 부르는 redis, elastic search 같은 애들이 있다. 

 

  첫번째 관계형 디비는 보통 ansi-sql 이라는 표준을 따르고 있으나, 각자 자체적으로 확장한 문법들이 많아서 한 SQL 제품에 맞는 쿼리를 다른 쪽에 던지면 보통 미세한 차이땜에 에러가 날 수 있지만, 몇 가지 제품에 쿼리들을 날려보다 보면 큰 틀에서 비슷비슷하다는 생각은 든다.(오히려 많이 차이가 나는 부분은 여러 관리 측면의 부분들이다) 관계형 디비의 장점은 관계의 꽃이라고 할 수 있는 join 기능을 통해 데이터 들 간의 관계를 쉽게 조회할 수 있다는 부분이 있지만 성능 문제 때문에 보통 하나의 서버 안에서만 join 이 가능하다고 보면 된다. 하나의 서버에 데이터를 모두 저장하기 때문에 응답 속도가 빠르지만, 데이터 양이 커지면 서버 용량이 모자라거나 메모리, cpu 에 부하가 걸리는 일도 생길 수 있다. NoSQL 이 나오기 전에 DB 계를 제패했었고 지금도 여전히 빅데이터와는 다른 특성의 데이터 영역들에서 잘 살고 있다고 본다. 참고로 mariadb는 오픈소스였던 mysql이 오라클에 넘어가게 되면서, 호환되는 오픈소스로 갈라진 버전이다. 두 개가 쿼리는 완전 동일했는데 현재는 서로 얼마나 차이가 나는진 잘 모르겠다. 

 

  NoSQL 에서 빅데이터 쪽은 보통 하둡(hadoop)이라는 여러 서버에 데이터를 나눠 보관할 수 있는 hdfs 란 파일 시스템을 기본으로 하는 hbase 디비가 있다. 해당 방식의 장점은 하나의 서버에서 지지고 볶는 관계형 디비와 달리, 토렌토나 컴퓨터들의 파워를 조금씩 나눠 쓰는 여러가지 그리드 형태의 서비스 처럼, 해야될 일을 분산되어 있는 데이터를 저장하고 있는 서버들에게 나눠 주어서 일을 시킨 후, 다시 결과를 모아서 보여줄 수 있는데 장점이 있는 듯하다. 많은 서버가 동시에 일을 나눠 하는 것이 가능해, 용량이 큰 데이터에 대해서 관계형 디비에 비해서 연산하기가 유리하기 때문에 Big데이터용 디비라고 불리는 것 같다. 이러한 분산 작업과 관련되어 맵, 리듀스, 셔플 같은 개념들이 쓰인다. 해당 데이터의 처리 과정이나 결과가 하둡 오리지날 방식에서는 비교적 복잡한 과정을 사용자가 직접 디자인해 줘야 하기 때문에, 해당 부분을 관계형 디비에서 사용하는 방식으로 커버를 씌워 준 것이, Hive(SQL 처럼 작업을 지시) 라고 보면 된다. Hive를 통하면 하둡에 적재된 데이터에 대해서 join 같은 형태의 관계형 작업의 에뮬레이션을 쉽게 지시할 수 있다. 개인적으로 이쪽은 명확히 이해는 못하고 있다고 생각하기 때문에, 아래 링크를 마지막으로 빅데이터 얘기를 마무리한다.

http://blog.acronym.co.kr/312

 

  Mongo 디비는 도규먼트 형식의 대표적인 디비로, 안에 json 형태의 문서를 담을 수 있다. 무엇 보다도 장점인 것 중 하나는 관계형 디비 같은 경우 입력되는 필드가 추가되면 alter table 을 통해 컬럼을 만들거나 수정해 맞춰주지 않으면 에러가 발생하지만(보통 스키마 변경이라고 한다. 컬럼 타입이나 갯수가 변경되면 스키마가 같이 변경되어 줘야 한다.), mongo 디비 같은 NoSQL 은 데이터의 변화에 따라 알아서 스키마를 고무줄 같이 조정하며 맞춰 주어서, DBA의 스키마 관리 역활이 사실 좀 모호해지는 듯 싶다. 그래서 비교적 어플리케이션의 쿼리 호출을 막 바꿀 수 있어 보통 개발자 들한테 인기가 많은 듯도 싶다. 비슷한 타입의 대체 가능한 디비가 뭐가 있는지는 잘 모르겠다.

 

  메모리 디비는 일단 가능한 많은 데이터들을 메모리에 올려 놓는 구조이다. 가능한 많은 데이터를 메모리에 올려 놓고 조회하는 구조로 쿼리에 대해 빠른 응답이 필요한 경우 사용하는 듯 하다. redis 는 키, 밸류 방식의 메모리 디비이다.

 

  Elastic search 디비와 검색엔진이 합쳐진 형태로 대용량 로그 검색이나 검색 엔진 등에서 주로 사용되는 듯하다. 

 

  여담이지만 오픈소스는 사용 비용은 무료지만 보통 통합 관리나, 성능 관리, 보안 등의 기능이 약한 경우가 있어, 그런 부분을 커스터마이즈 하여 확장한 관련 솔루션을 추가로 구입해(외국엔 그런 걸로 잘 사업하며 먹고 사는 기업들도 많은 듯한다) 사용해야 하는 경우도 많기 때문에, 결국 유지 비용이 비슷비슷해지는 경우도 종종 있다고 한다.

 

  그럼 요 정도로 디비 종류 얘기는 마무리하고 혹 잘몰라서 잘못된 얘기를 했더라도 넓은 맘으로 이해해 주길 바라며 글을 마친다.

 

 

 

1
2017.2.25 by 자유로운설탕
cs

 

 

 

posted by 자유로운설탕
2017. 2. 23. 21:33 프로그래밍

  이번 시간에는 3교시때 얘기한 암복호화 하는 샘플을 찾아서 이용해 보려고 한다.

 

[목차]

0. 왜 파이썬 공부에 구글을 이용하는게 좋은가?

1. 언어를 바라보는 방법. 파이썬을 어떻게 바라봐야 할까?

2. 파이썬 설치와 환경, 버전 선택 하기의 이유.

3. 만들고자 하는 기능을 모르는 조각으로 나눠 조사해 보기

4. 데이터 베이스에서 내용 가져와 출력하기

5. 암호화 모듈을 이용해 암복호화 해보기

6. 퍼즐 조각들을 합쳐보기

7. 엑셀 파일 사용해 보기 -> 부록 : fuction 을 이용해서, 코드 정리해 보기

8. 정규표현식을 왜 사용해야 할까? 언어속의 미니 언어 정규표현식 살펴보기

9. 입력과 결과를 GUI 화면과 연결해 보기

10. Whois API 이용해 보기

11. 웹페이지 호출해 내용 파싱 하기(BeautifulSoup 그리고 한계)

12. 자동화 - 웹 자동화(with Selenium)

13. 자동화 - 윈도우즈 GUI 자동화(with pywinauto)

14. 자동화 - 작업 자동화

15. 수학 라이브러리 살펴보기

16. 그래픽 라이브러리 살펴보기

17. 머신러닝에서의 파이썬의 역활

18. 웹 프로그래밍 - Legacy Web

19. 웹 프로그래밍 - Flask 살펴보기(feat. d3.js)

20. 웹 프로그래밍 - Django 살펴보기

21. 정리 - 이런저런 이야기

 

 

 

 

[들어가면서]

  3교시 때 아래까지 얘기를 했었다. 그림의 회색 부분을 위한 코드 샘플을 찾는 중이다. 

 

  "2 번째로, aes256으로 암, 복호화 하기 위한 모듈을 찾아보자. 구글에서 'python 3 aes256' 로 찾으면 처음에 스택오버플로우 글이 나오고, 두번째로 우리나라 분이 정리한 문서가 하나 나온다.

http://blog.dokenzy.com/archives/1997"

 

 

 

 

[암호화 모듈 설치]

  해당 샘플을 이용하기 위해 pycrypto 모듈을 아래와 같이 일단 pip 로 설치하려고 해본다. cmd 창에 아래 명령어로 pycrypto 를 설치한다.  

c:\Python\code>pip install pycrypto

 

  그런데 아래와 같은 에러가 발생한다. 아마도 pycrypto 가 더 이상 유지 보수가 안되거나 해서, 파이썬 공식 저장소에 pycypto 가 빌드된 파일이 없어서 빌드를 하려다가, 빌드에 쓸 적절한 컴파일러가 컴퓨터 내에 없어서 에러가 나는 것 같다. 

 error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools

 

  에러에 표시된 해당 페이지로 가면, 아래와 같이 Visual C++ 2015 Build Tools 링크가 나온다.

 

 

  막상 설치하려니 궁금한게 하나 생긴다. 에러에서는 Visual C++ 14.0 버전을 설치하라고 하는데, 2015 버전이 14.0 이 맞을까? 구글에서 'visual studio 2015 version number' 찾아 아래 위키의 내용을 보면 14.0 이 2015가 맞는다고 한다. 그럼 고민 하지 말고, 링크를 클릭해서, Visual C++ Build Tool 을 다운 받아 설치 한다.

https://en.wikipedia.org/wiki/Microsoft_Visual_Studio

 

  설치가 잘 완료된 후 다시 pip 설치 명령을 돌리면 아래와 같이 정상적으로 설치된다.

c:\Python\code>pip install pycrypto
Collecting pycrypto
  Using cached pycrypto-2.6.1.tar.gz
Installing collected packages: pycrypto
  Running setup.py install for pycrypto ... done
Successfully installed pycrypto-2.6.1

 

 

  이쯤 와서 정리해 보면 파이썬에서 모듈을 설치하는 방법은 3가지쯤 있어 보이는데, 첫번째는 pip 를 이용해서 패키지 이름을 지정해 공식적인 저장소에서 다운 받아 가져오는 것, 2번째는 다른 사람들이 빌드해 설치본으로 만들어 놓은 exe 형태의 인스톨 버전을 웹에서 다운받아 설치하는 방법, 세번째는 pip 명령어 뒤에 github 같은 웹경로나 로컬 경로를 지정해 wheel 이라는 확장자의 파일을 이용해 설치한다. wheel이 뭔지 궁금해 구글을 찾아보니 zip 파일의 확장자를 wheel 이라고 바꾸어 저장하는 것으로 아마 그 안엔 이미 컴파일된 모듈이 들어 있어 파이썬이 다운 받아 단지 압축을 풀어 모듈 폴더로 복사 함으로써 모듈이 설치되는 원리 같다. 설치 장소는 c:\Python\Lib\site-packages\ 안이다. 아래 링크의 글을 참고...

https://pypi.python.org/pypi/wheel

 

  ※ 뭔가 환경이 바뀌었는진 모르겠는데, 처음 pycrypto 를 설치 했을때는 비슷한 종류의 에러긴 한지만, 명확히 뭐를 설치하라고는 안나오고, "Unable to find vcvarsall.bat..." 요런 식으로만 나와서 구글에서 'python3 install crypto Unable to find vcvarsall.bat' 게 찾아서, 아래 페이지로 가서 wheel 파일을 설치해 해결했었다. 근데 컴파일러 설치가 정석인 것은 같다.

http://stackoverflow.com/questions/32800336/pycrypto-on-python-3-5

 

[64비트]

pip install --use-wheel --no-index --find-links=https://github.com/sfbahr/PyCrypto-Wheels/raw/master/pycrypto-2.6.1-cp35-none-win_amd64.whl pycrypto
[32비트]

pip install --use-wheel --no-index --find-links=https://github.com/sfbahr/PyCrypto-Wheels/raw/master/pycrypto-2.6.1-cp35-none-win32.whl pycrypto 

 

 

 

[암호화 소스 실행]

  그럼 아래 블로그의 소스를 가져와 보자. 테스트 결과 실행이 잘 되니 내용은 바꿀 필요는 없고, 주석만 조금 제거하고 설명을 추가하도록 하겠다. http://blog.dokenzy.com/archives/1997

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#-*- coding: utf-8 -*-
 
# Python 3.4
# author: http://blog.dokenzy.com/
# date: 2015. 4. 8
 
import base64
import hashlib
from Crypto import Random
from Crypto.Cipher import AES
 
# 아마 특정한 블록 사이즈를 채우기 위해서 입력된 값을 임의의 값으로 패딩(채워주기) 하는 코드 인 듯...
BS = 16
pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS).encode()
unpad = lambda s: s[:-ord(s[len(s)-1:])]
 
# 초기화 코드 인듯
def iv():
    """
    The initialization vector to use for encryption or decryption.
    It is ignored for MODE_ECB and MODE_CTR.
    """
    return chr(0* 16
 
# 2교시때 설명했 듯이 클래스는 구조를 잘 잡아주는 껍데기 이다.
class AESCipher(object):
    """
    https://github.com/dlitz/pycrypto
    """
 
    def __init__(self, key):
        self.key = key
        #self.key = hashlib.sha256(key.encode()).digest()
 
    # 메시지를 암호화 하는 함수 
    def encrypt(self, message):
        """
        It is assumed that you use Python 3.0+
        , so plaintext's type must be str type(== unicode).
        """
        message = message.encode()
        raw = pad(message)
        cipher = AES.new(self.key, AES.MODE_CBC, iv())
        enc = cipher.encrypt(raw)
        return base64.b64encode(enc).decode('utf-8')
    
    # 메시지를 복호화 하는 함수
    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        cipher = AES.new(self.key, AES.MODE_CBC, iv())
        dec = cipher.decrypt(enc)
        return unpad(dec).decode('utf-8')
 
# 암호화 키 
key = 'abcdefghijklmnopqrstuvwxyz123456'
 
# 테스트 용 문자열
message = '한글을 테스트 합니다.'
 
# 테스트 용 문자열이 암호화 됬을 때 만들어 지는 값
_enc = 'gOXlygE+qxS+69zN5qC6eKJvMiEoDQtdoJb3zjT8f/E='
 
# 테스트용 문자열을 암호화 하고, 미리 암호화 된 값을 복호화 하기  
enc = AESCipher(key).encrypt(message)
dec = AESCipher(key).decrypt(_enc)
 
# 암호화 복호화 한 값이 서로 같음을 비교해 증명 true, true 가 나오면 같다고 증명된다.
print(_enc == enc)
print(message == dec)
cs

 

  그럼 위의 파일을 aes_example_in_python.py 로 저장하고 실행 한다. 저장하고 실행하는 방법이 기억이 안나면 2교시 때 자세히 설명한 부분을 다시 보고 오면 된다.

c:\Python\code>python aes_example_in_python.py
ImportError: No module named 'winrandom'

 

 

  실행을 했는데 또 다른 에러가 난다. 에러를 찾아보기 위해 구글에서 'python 3.5 winrandom' 이라고 찾아본다.  
https://stackoverflow.com/questions/24804829/another-one-about-pycrypto-and-paramiko

 

  아래와 같이 설치된 파일에서 nt.py 파일을 찾아서, 아래 문장을 수정해 저장하라고 그런다.
Problem is solved by editing string in crypto\Random\OSRNG\nt.py:

import winrandom -> from . import winrandom

 

  아래 파일을 열어서 내용을 수정해 준다. import winrandom 이 들어간 내용을 수정해 준다. 

  c:\Python\Lib\site-packages\Crypto\Random\OSRNG\nt.py

 

  다시 실행해 본다. 그럼 아래와 같이 True, True 라고 정상적으로 실행되어 결과가 나온다.

c:\Python\code>python aes_example_in_python.py
True
True

 

 

  ※ 수정한 문장에서 . 이 궁금하면 아래 링크들을 본다. 아마도 pycryto 가 2.x 대 버전만 공식적으로 지원 해서 3.x 대와 문법이 안맞아 그런거 같다고는 하는데 확실하진 않다. (2014년 6월이 최종 업데이트 날짜다)

  http://stackoverflow.com/questions/7279810/what-does-a-in-an-import-statement-in-python-mean

  https://wikidocs.net/1418

 

  ※ 새로운 암호화 모듈을 찾아보기 위해 구글에서 'python 3.6 pycrpto' 를 찾아보니, pycryptodome 이라는 모듈이 대체 되었다고 한다. 실제 프로젝트를 할때는 이와 같이 최신으로 유지보수 되는 많이 쓰는 라이브러리를 쓰는게 맞을 듯 싶다.

http://stackoverflow.com/questions/41813030/problems-with-installation-pycrypto-in-python-3-6

https://dzone.com/articles/an-intro-to-encryption-in-python-3

 

 

  그럼 5교시를 마치고, 6교시때는 4교시때 사용했던 MSSQL 와 함께, 5교시때의 암호화를 같이 머지해서, 만들려 그랬던 기능을 만들어 보도록 한다.

 

 

[추가]

파이썬 3.7의 경우는 본문에 있는 한글 에러 문제가 해결되어, pip install pycryptodome 으로 설치해 사용하면 됩니다^^

 

위의 3.5용 소스는 밑에 댓글 달아주신 것 같이 pycryptodome 사용하면 에러가 나서 아래 코드를 참조하세요. 

https://github.com/bjpublic/python_study/blob/master/%EC%98%88%EC%A0%9C%20%EC%86%8C%EC%8A%A4%20%EC%BD%94%EB%93%9C/05%EA%B5%90%EC%8B%9C/pycrypto_aes256_sample.py

 

 

1
2017.2.24 by 자유로운설탕
cs
posted by 자유로운설탕
2017. 2. 18. 19:22 프로그래밍

  4번째 시간이다. 이번 시간에는 지난 시간에 구현을 위해 나눈 기능 중 DB 와의 연결 부분을 구현하기 위해 MSSQL Express DB 서버를 설치하고, 어플리케이션 용으로 이런 저런 세팅 후, 쿼리를 날려서 테이블 내의 값을 가져오려 한다. 아래의 3교시 그림을 기준으로 하면 회색 박스로 표시되 있는 MSSQL Database 항목이다.  MSSQL 설치 및 원격 연결 설정, DB 생성 및 사용자 생성 부분은 이미 아시거나 설치되어 있다면 건너뛰고 보면 되겠다. 풀버전으로만 설치해 보셨던 분들은 express 버전은 조금 다른 듯 하니 설정 부분만 보셔도 될듯 싶다.

 

 

[목차]

0. 왜 파이썬 공부에 구글을 이용하는게 좋은가?

1. 언어를 바라보는 방법. 파이썬을 어떻게 바라봐야 할까?

2. 파이썬 설치와 환경, 버전 선택 하기의 이유.

3. 만들고자 하는 기능을 모르는 조각으로 나눠 조사해 보기

4. 데이터 베이스에서 내용 가져와 출력하기

5. 암호화 모듈을 이용해 암복호화 해보기

6. 퍼즐 조각들을 합쳐보기

7. 엑셀 파일 사용해 보기 -> 부록 : fuction 을 이용해서, 코드 정리해 보기

8. 정규표현식을 왜 사용해야 할까? 언어속의 미니 언어 정규표현식 살펴보기

9. 입력과 결과를 GUI 화면과 연결해 보기

10. Whois API 이용해 보기

11. 웹페이지 호출해 내용 파싱 하기(BeautifulSoup 그리고 한계)

12. 자동화 - 웹 자동화(with Selenium)

13. 자동화 - 윈도우즈 GUI 자동화(with pywinauto)

14. 자동화 - 작업 자동화

15. 수학 라이브러리 살펴보기

16. 그래픽 라이브러리 살펴보기

17. 머신러닝에서의 파이썬의 역활

18. 웹 프로그래밍 - Legacy Web

19. 웹 프로그래밍 - Flask 살펴보기(feat. d3.js)

20. 웹 프로그래밍 - Django 살펴보기

21. 정리 - 이런저런 이야기

 

 

 

 

[들어가면서] 

  개인적인 의견이지만 파이썬을 사용하기 전에 perl(펄) 이라는 언어를 조금 사용하고 있었는데, 파이썬은 perl 이 현대적 스타일을 지니고 다시 태어난 듯한 느낌이 든다. perl 은 리눅스 쉘 환경을 언어로 축약해 놓은 것 같은 재밌는 느낌도 있고, 30년의 오랜 역사를 통해(파이썬도 25년이 됬다고 해서 놀랐다) 방대하게 축적된 라이브러리와 참고 가능한 코드들이 구글에 많아 필요한 기능을 만들기 편하다고 생각했는데(물론 파이썬 보다 축약적 표현을 많이 써서 코드 가독성은 은근 암호문 같아서 확실히 떨어지는 것 같긴 하다), 파이썬을 경험해 보고 비슷하지만 무척 현대적으로 깔끔하다는 느낌을 받았다. 또 파이썬은 프로그래밍 하는 사람의 스타일에 따라 perl 같은 라이트하게 만들어 유틸성으로 사용하는 스크립트형 코딩도 가능하고, java 나 c# 같은 구조적인 언어가 가진 객체 지향이나, 웹의 mvc 같은 구조의 방식을 취할 수도 있어 스타일을 선택해 사용이 가능하도록 스펙트럼을 넓혀 놓은 것 같다. 기회가 닿는 다면 파이썬과 비슷한 느낌이지만 고전성과 정규식의 미가 있는 펄(perl) 이라는 언어도 한번 사용해 보길 추천한다.

 

 

  그럼 잡담은 그만하고(야매지만 할말은 많다 - -;) mssql 을 설치하고 python 으로 필요한 모듈을 설치하고, 샘플 코드를 만들어 보도록 해보자. 참고로 순서는 아래와 같으니 무엇을 하려고 진행하는 건지 의식적으로 생각하면서 따라해 보자

  1) MSSQL 설치

  2) 서비스 설정

  3) 실습용 DB 및 사용자 설정

  4) 테이블 생성과 데이터 입력

  5) python 으로 조회해 보기

 

 

 

 

1) MSSQL 설치

 

  먼저 구글에서 다음과 같이 다운로드 가능한 링크를 찾는다 'mssql 2016 express download' 두 번째로 나오는 아래의 링크에서 SQL Server 2016 express SP1 을 다운로드 한다.

  https://www.microsoft.com/ko-kr/sql-server/sql-server-editions-express

 

 

  설치 파일을 클릭해 설치를 클릭하고, 아래와 같은 화면에서 기본 설정을 선택 한다. 라이선스를 수락하고(요건 간단해서 스크린샷 생략), 기본 설치 위치로 설치한다(스크린샷 생략). 400 메가 정도의 다운로드가 시작되며 설치가 된다(설치가 예전에 비해 간략해진 듯 하다)

 

 

  그럼 아래와 같이 설치가 완료되었다는 화면이 나온다. 그냥 닫지 말고 아래의 SSMS 설치 버튼을 클릭한다(SSMS 는 SQL Server Management Studio의 약자로 SQL 서버 접속용 클라이언트 이다 - 오라클로 따지면 Oracle Developer 나 오렌지, 토드 같은 툴이다. 앞으로 우리는 SSMS 에서 테이블 등을 만들거나 조회해 준비와 검증을 해보고, 이후 파이썬으로 개발을 할 예정이다).

 

 

  아래 페이지로 이동되면, SQL Server Management Studio 16.5.1 을 다운받아 설치 한다. (900 메가 정도 된다. 배보다 배꼽이 더 크다더니...)

  https://msdn.microsoft.com/ko-kr/library/mt238290.aspx

 

 

  다운 받은 파일을 실행하고 아래와 같이 설치를 시작한다.

  자 이렇게 되면 MSSQL 설치는 무사히 완료됬다.

 

 

 

 

2) 서비스 설정

 

  그럼 서비스 설정을 해보자. 원래 개인적으로 이런저런게 막혀서(특히 원격에서 연결이 안되서 좀 헤멨다) 구글을 찾아 해결 했지만, 해당 부분은 파이썬 공부와 좀 거리가 멀기 때문에 선택과 집중을 위해 헤멧던 검색 과정은 생략하도록 하겠다. 설치된 프로그램에서 SQL Server Management studio 를 실행 하자.

 

 

  SSMS 가 뜨면서 "서버에 연결" 하기 창이 나오면, 서버 이름이 비어 있기 때문에(예전엔 디폴트로 표시됬는데...), 드랍박스를 열어서 "더 찾아보기"를 선택한다. 이후에 서버 찾아보기의 로컬 서버 탭에서 내가 설치한 데이터 베이스를 선택 한다.    

 

 

  이제 서버 이름이 나오고 인증을 Windows 인증 상태에서"연결" 버튼을 눌러 연결한다. (SQL Server는 인증 방식이 두 가지가 있는데, 1번째로는 SQL 설치된 서버에서는 Windows 인증으로 id/pass 없이 관리자 계정으로 들어갈 수 있고, 2번째로는 사용자를 생성하거나 SA(System Administrator) 계정을 활성화 시켜서 id/pass 를 넣어서 들어갈 수 있다)

 

 

  그럼 아래와 같이 개체 탐색기 창이 나타난다. MSSQL 을 처음 설치하면 Windows 인증으로만 로그인이 가능하다(아직 활성화되거나 만들어진 사용자가 없기 때문에). 그런데 우리가 만들 파이썬 프로그램은 id/pass 를 넣어서 SQL Server에서 연결해 사용할 것이므로, 해당 id/pass로 로그인 가능한 옵션을 켜줘야 한다. SQL 서버 이름을 선택하고 마우스 오른쪽 버튼을 눌러서 컨택스트 메뉴를 띄운 후 맨 아래 보이는 "속성" 메뉴를 클릭한다.

 

 

  그럼 "서버 속성" 창이 뜬다. 왼쪽 트리에서 보안 항목을 선택하면 서버 인증 옵션이 보이는데, 디폴트는 아래와 같이 Windows 인증 모드가 체크되어 있는데, "SQL Server 및 Windows 인증모드"를 선택 후 "확인" 버튼을 눌러 적용한다. 그럼 SQL 서버를 다시 시작해야 된다는 Alert 이 뜨며 적용이 된다.

 

 

  SQL 서버 재시작은 cmd 명령어로 하거나, 컴퓨터를 재부팅 해도 되긴 하겠지만 시작 > 모든 프로그램에서 Microsoft SQL Server 2016 > 구성도구 > "SQL Server 2016 구성 관리자" 를 실행 한다. 

 

 

 그럼 아래와 같은 "SQL Server Configuration Manager" 창이 뜨는데, 일단 서비스 재시작을 하기 전에 할 일이 하나 추가되었다. 현재 세팅 상태로만 운영하게 되면 SSMS 에서는 id/pass 로 잘 접속이 되는데, python 이나 telnet 으로는 접속이 안되는 일이 발생했다. 구글을 찾아보니 아래와 같은 안내가 있어 추가 적인 세팅을 한 후 서비스 재시작을 하려 한다. 

http://stackoverflow.com/questions/12774827/cant-connect-to-localhost-on-sql-server-express-2012-2016

 

 

  먼저 TCP/IP 를 enable 시킨다. 왼쪽에서 "SQL Server 네트워크 구성" > "SQLEXPRESS에 대한 프로토콜" 을 선택하고, 오른쪽에서 TCP/IP 항목을 더블 클릭 한다. "프로토콜" 탭에서 Enabled 를 "예"로 바꾸어 준다.

 

 

  그리고 동일한 화면의 IP 주소 탭으로 이동해서 맨아래의 "IPALL" 파트에서 "TCP Dynamic Ports" 항목을 지우고, "TCP Port" 항목에 MSSQL 디폴트 port 인 "1433" 을 넣은 후 확인 버튼을 누른다. 그럼 앞서와 마찬가지로 서비스를 재시작 해야된다는 메시지가 나온다.   

 

 

  서비스 재시작을 위해서, 다시 왼쪽에서 "SQL Server 서비스"를 선택하고, 오른 쪽에서 "SQL Server (SQLEXPRESS)" 항목을 클릭 후 마우스 오른 쪽 버튼으로 컨텍스트 메뉴를 띄워서, "다시 시작" 클릭 해, 서비스를 종료했다 다시 시작한다.

 

  자 이렇게 하면 원격 서비스 설정이 완료이다. 이제 부터는 MSSQL 을 사용하기 위해 세팅하는 부분을 진행한다.

 

※ 파이썬을 돌리기 전에 간단히 서버 연결을 확인 하려면, telnet 서비스를 설치하고 cmd 창에서 'telnet localhost 1433' 으로 정상적으로 연결되는지 보면 된다. 텔넷은 아래 링크에서...

  https://opentutorials.org/module/2160/12506

 

 

 

 

3) 실습용 DB 및 사용자 설정

 

  개체 탐색기에서 "데이터베이스" 항목을 선택 후 컨택스트 메뉴를 띄워(이제 마우스 오른쪽 버튼 누르라는 얘기는 생략한다--;), "새 데이터베이스" 항목을 선택한다.

 

 

  데이터베이스 이름을 "mytest" 라고 입력하고(여러분이 좋아하는 다른 이름을 입력해도 되지만, 그러면 앞으로 제공할 소스에서 디비 이름 항목을 여러분 걸로 수정해 주어야 한다). 확인을 누른다.

 

 

 

 그럼 아래와 같이 별로 한것도 없는데, mytest 란 방금 만든 DB가 보이게 된다.

 

 

 

  자 이제 파이썬 프로그램에서 사용할 사용자를 만들어 보자. "보안" > "로그인" 항목을 선택하고, 컨텍스트 메뉴를 띄워 "새 로그인" 항목을 실행한다.

 

 

  "로그인 - 신규" 창이 뜨면, 왼쪽에서 "일반"을 선택 하고, 로그인 이름 "pyuser"(이것도 역시 원하면 취향대로 이름 만드시고, 나중 소스에서 수정!), "SQL Server 인증" 라디오 버튼을 클릭하고, 암호에 "test1234", 암호 확인에 "test1234" 를 넣는다. 공부하는 건데 암호가 만료되면 귀찮으므로(실제 운영시는 정책을 설정해 패스워드를 주기적으로 바꿔 주는게 보안 적으로 맞다) 아래와 같이 "암호 정책 강제 적용" 체크 박스를 끈다.

 

 

  이후 왼쪽에서 "서버역활" 항목을 클릭하고 sysadmin 을 클릭한다.(요 부분도 사실 admin 권한이므로 실제 웹어플리케이션 등 운영시는 권한을 제한하여 사용해야 한다).

 

 

  마지막으로 "사용자 매핑"을 선택하고, 오른쪽에서 "master" 데이터베이스를 선택하여 하단에서 "db_owner" 권한을 체크하고(이것도 "디비의 주인" 역활이기 때문에 운영에서는 과도한 권한임, master 데이터 베이스는 시스템의 여러 설정 값이나, 디비 스키마(디비구조 설계도) 등이 들어 있는데, 나중에 테이블 컬럼명을 얻어오는 코드에서 사용할 예정이다), 또 우리가 만든 "mytest" 데이터베이스를 선택하여 동일하게 "db_owner" 권한을 체크한다.  그리고 하단의 "확인" 버튼을 눌러 사용자 생성을 완료한다. 이렇게 되면 master db와 , mytest db 에 db_owner 권한을 가진, sysadmin 역할을 지닌 pyuser 사용자가 생성된다

 

 

  이후 SSMS 상단의 "파일" > "개체 탐색기 연결" 메뉴를 띄워 인증 부분을 "SQL Server 인증" 으로 바꾸고 우리가 생성한 id/pass 를 입력한다. 이후 "연결" 버튼을 누른다. 

 

 

  이제 개체 탐색기를 보면 2개의 똑같은 연결 항목이 있을 것이다. 항목 제목을 보면 위쪽은 첨에 우리가 Windows 인증으로 연결한 항목이고, 아래쪽은 지금 pyuser 로 연결한 항목이다.

 

 

  자 그러면 초보자들은 헷깔릴수 있으니, 위의 항목을 선택 후 컨택스트 메뉴를 띄워 "연결 끊기" 를 클릭한다.

 

 

  연결이 끊긴 후 개체 탐색기 메뉴를 보면 우리가 2번째 만든 pyuser 에 대한 항목만 하나 남게 된다. 이제 "mytest" DB 항목을 선택 하고, 컨텍스트 메뉴에서 "새 쿼리" 를 선택 한다.

 

 

  그럼 오른 쪽에 쿼리 창이 열리면서 커서가 빤짝빤짝 거린다. 쿼리창 상단에 마우스를 오버해 올려보면, mytest (pyuser (56)) 이라고 현재 사용하는 DB와 사용자 정보가 나온다.

 

 

  마지막으로 쿼리창에 "select SYSTEM_USER" 라고 입력후, 마우스로 드래그해 선택한다. 그리고 F5키 를 누른다(이것은 SSMS 상단 메뉴에서 "쿼리 > 실행" 을 누르는 것과 동일하다). 해당 명령은 등록된 사용자를 보여주는 명령어로 하단 결과 창에 우리가 등록한 "pyuser"가 보인다. (참고로 마우스로 드래그하여 선택하지 않으면 F5를 눌렀을때, 쿼리 창에 있는 모든 쿼리가 다 실행된다.)

 

  이제 MSSQL 을 파이썬에서 이용하기 위한 모든 준비가 끝났다(개인 적으로 관련 스크린샷 만드는 게 은근 힘들었어서, 큰 산을 넘은 듯하다 --;)

 

 

 

 

4) 테이블 생성과 데이터 입력

 

  이제 그러면 DB 에 테이블을 하나 만들어 보자. 구글에서 "mssql table create sample" 라고 검색해 보자. MSDN 설명은 보통 모든 옵션을 다 나열해서 장황하니 아래와 같이 좀 간략한 샘플을 제공하는 페이지를 참고한다.

  https://www.techonthenet.com/sql_server/tables/create_table.php

 

 

  간략히 설명하면 아래와 같다.

1
2
3
4
create table 소유자.테이블이름 (
   "컬럼이름1" " 담을 데이터형태" "각종제약조건(null 여부, primary, default, check 등)"
   "컬럼이름2" .... 
)
cs

 

 

  소유자를 안넣게 되면 현재 사용자의 테이블이 생성되기 때문에 현재 환경에서는 pyuser 가 dbowner 권한 이기 때문에, dbo(db owner)가 무조건 붙게 된다. 담을 데이터 형태는 파이썬과 마찬가지로 int, char, float 등등으로 컬럼에 담을 데이터의 형을 지정하게 된다. 제약 조건은 null, not null, primary, constraint, identity, foreign key, default value 등 여러가지 항목들이 있으나 해당 부분은 MSSQL 뿐만 아니라 표준 SQL 전반에 대한 공통된 내용이므로 "헤드퍼스트 SQL" 이나 잘 정리되 있는 블로그들을 참조한다(차후 개발 보안 관련 글들을 올릴때 SQL 의 전반적인 내용에 대해서 간단히 다룰 예정이긴 하다). 여기서는 null, not null 만 보자. null 은 해당 컬럼에 값을 넣지 않아도 관계없다는 거고, not null 은 꼭 어떤 값이 들어가야 한다는 얘기다.

 

  예를 들어 test 테이블에 no, name, card 라는 컬럼이 있고, card 라는 항목이 nullable 이라면 "1", "홍길동" 이런 식으로 3번째 card 값을 생략하고 한 행을 만들 수 있다(카드가 없는 사람도 있을 수 있기 때문에, 해당 card 라는 컬럼에 데이터가 비어 있는걸 가능하게 하는 것이다). 또 null 이라는 개념은 join 등에서도 해당 되는 대상이 없는 부분을 판단할때 같은 때도 사용하지만, 테이블 만의 개념을 설명하면 위와 같이 단순히 이해하면 된다. 또 데이터형 뒤에 null, not null 을 안 써준 경우 mssql은 기본적으로 null 형태라고 판단하긴 하는데, null 을 명시적으로 쓰는게 명확한 것 같긴하다. null 에 대한 고찰은 구글에서 'null 개념' 이라고 검색하여 아래와 같은 글들을 참고해 본다.

  http://slowalk.tistory.com/2181

 

 

  그럼 위의 지식을 기반으로 우리 실습에 사용할 supermarket 이란 테이블을 만들어 본다.

1
2
3
4
5
6
7
CREATE TABLE [dbo].[supermarket](
    [Itemno] [int] NULL,
    [Category] [char](20) NULL,
    [FoodName] [char](30) NULL,
    [Company] [char](20) NULL,
    [Price] [int] NULL
)
cs

 

 

  자 테이블의 내용을 보면 주인은 DBO(DB Owner = pyuser)이고, 컬럼은 아이템번호(itemno), 종류(category), 과자이름(foodname), 제조사(company), price(가격이다), 모두 비어 있을 수 있는 null 을 지정했고, 아이템번호와, 가격은 int 로 지정했다. 나머지 값들은 20, 30개의 문자로 이루어진 문자열 이다(mssql 은 대소문자 안가린다). 그럼 위의 소스를 긁어서 아까 실행해 놓은 쿼리 창에 붙여 넣고 내용 전체를 선택 후 F5키를 누른다. 하단 결과 창에 명령이 완료되었다고 뜨며, 왼쪽에 우리가 만든 supermarket 테이블이 보이게 된다

 

 

  이후 우리가 만든 테이블을 한번 내용을 조회해 보자. 아래의 소스에서 첫번째 줄인 "select ~ (nolock)" 부분을 복사해서 쿼리 창에 붙여 넣는다. '--' 로 시작되는 줄들은 주석 표시로, 쿼리가 처음 인 분을 위한 설명을 위해 넣었다

1
2
3
select * from supermarket(nolock)
-- 슈퍼마켓 테이블(supermarket) 로부터(from) 모든걸(*) 가져와봐(select) 
-- 다른거랑 부딛치지 말구(nolock)
cs
 

 

  근데 아래와 같이 컬럼 이름만 표시되고 빈 내용만 있다.

 

 

  우리가 아직 테이블만 만들고 데이터는 넣지 않았으니 당연하다. 그럼 데이터를 넣는 방법을 찾아보기 위해서 구글에서 "mssql insert sample"로 검색한다. 아까와 똑같은 techonthenet 사이트의 내용을 참고한다.

  https://www.techonthenet.com/sql_server/insert.php

1
2
3
4
INSERT INTO 테이블
(컬럼1, 컬럼2, 컬럼3)
VALUES
(넣을값1, 넣을값2, 넣을값3);
cs

 

 

  해당 방식을 이용해서 supermarket 에 넣을 쿼리를 만들면 아래와 같다. 역시 아래 소스를 긁어서 쿼리 분석기에 넣고 선택 후 F5키를 누른다(이제 요 긁어서~F5 설명도 익숙해 지셨을 테니 슬슬 생략 하고 "쿼리를 실행한다" 라고 표현한다.) 아래와 같은 4개 메시지가 결과 창에 나오면 성공한 것이다(4개의 데이터 건이 각각 들어갔으므로, 4개 행이 영향을 받았다고 나온다)
  (1개 행이 영향을 받음)
  (1개 행이 영향을 받음)
  (1개 행이 영향을 받음)
  (1개 행이 영향을 받음)
 

1
2
3
4
5
6
7
8
9
10
11
12
insert into supermarket
values (1,'과자', '초코파이', '오리온', 3000)
-- 슈퍼마켓 테이블(supermarket)안에(into) 값들(1,'과자', '초코파이', '오리온')을 넣어줘(insert)
 
insert into supermarket
values (2, '음료수', '크라운 커피', '크라운', 1000)
 
insert into supermarket
values (3, '음료수', '오리온 식혜', '오리온', 1300)
 
insert into supermarket
values (4, '과자', '크라운 산도', '크라운', 500)
cs

 

 

  그럼 아래 쿼리를 다시 실행해 본다.

1
select * from supermarket(nolock)
cs

 

 

  이제 화면과 같이 결과가 잘 나오게 된다. 

 

 

  참고로 아래와 같은 쿼리들도 추가로 돌려서 sql select 문의 여러가지 면들을 느껴보자.

1
2
3
4
5
6
7
8
9
10
11
-- 과자만 보고 싶어(category = '과자')
select * from supermarket(nolock) where category = '과자'
 
-- 1000원 이하(price <= 1000) 상품만 보고 싶어
select * from supermarket(nolock) where price <= 1000
 
-- 결과 중에 상품이름과, 회사만 보고 싶어
select FoodName, Company from supermarket(nolock) 
 
-- 과자이름 가나다 순으로 보고 싶어
select * from supermarket(nolock) order by FoodName
cs

 

  그럼 테이블 생성 및 샘플 데이터 입력 파트가 끝나게 되었다

 

 

 

 

5) python 으로 조회해 보기

 

  여기까지 오기전까지 MSSQL 설치 및, 세팅, 테이블 생성과 데이터 입력 후 조회를 해봤다. 무척 번거롭고 긴 과정이라고 느꼈을 수도 있겠지만, 앞 시간에서 얘기했듯이 4교시 앞 부분의 모든 과정은 python 하고 직접적인 관계가 없다. 어찌보면 일반적인 프로그래밍 요소에 대한 설명을 한 서비스 챕터 개념이다. 반대로 얘기하면 여기서 얻은 mssql(그리고 겪어봄 알겠지만 많이 비슷한 SQL 표준을 따르는 oracle, mysql 같은 관계형 DB 들, 하둡베이스의 hive 등)에 대한 지식들은 다른 언어를 할때도 역시 적절히 응용해 사용할 수 있다. 아마 나중에 lua, java 같은 다른 언어를 할 때도, 지금 알게된 이 지식 때문에, SQL을 호출하는 부분이 좀 더 수월하게 느껴지게 될 것이다. 프로그래밍은 코딩 작업이 아니다. 자기가 아는 구체적인 지식들을 코드라는 수단을 이용해 표현하는 것일 뿐이다. 구현할 주제와 관련된 모든 것을 잘 파악하고 있다면 구현은 비교적 간단해 진다. 그래서 같은 회사안에서도 바쁜척 하면서 설렁설렁 살아가는 프로그래머들도 있다. 요즘 많이 얘기되는 폴리글랏 프로그래밍도 어떤 측면에서는 같은 맥락인 듯 싶다. 새로운 언어를 빨리 배우는 능력은 언어와 연결된 배경을 잘 아는데서 기인할 수도 있다.

 

 

  우선 python 에서 mssql 을 호출하려면 어떻게 해야되는지 알기위해 구글을 검색해 보자. 구글에 "python 3 mssql" 로 검색한다. 맨위에 아래의 링크가 나오게 된다.

  http://www.c-sharpcorner.com/blogs/connect-ms-sql-server-2012-with-python-35

 

 

  내용을 참고해 보면 c# 언어에 대한 가이드긴 하지만 pymssql 이라는 모듈을 사용하고 아래의 명령으로 설치하라고 한다. cmd 창으로 가서 아래 명령어를 복사해 사용한다.

1
pip install pymssql  
cs

 

c:\>pip install pymssql
Collecting pymssql
  Using cached pymssql-2.1.3-cp35-cp35m-win_amd64.whl
Installing collected packages: pymssql
Successfully installed pymssql-2.1.3

 

  정상적으로 설치가 되었다고 문구가 나온다. 그럼 이제는 프로그램 소스에 이용할 관련 샘플을 찾아보자. "pymssql python sample" 이라고 찾으면 제일 위에 공식 홈에서 나온 설명 페이지가 나온다.

  http://pymssql.org/en/latest/pymssql_examples.html

 

 

  해당 페이지의 코드 중에, Basic Features 부분에서 테이블 생성과, 인서트 부분을 제외하고 셀렉트 코드 기준으로 적당히 편집해 가져오면 아래와 같다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
import pymssql
conn = pymssql.connect(server, user, password, "tempdb")
cursor = conn.cursor()
 
cursor.execute('SELECT * FROM persons WHERE salesrep=%s''John Doe')
row = cursor.fetchone()
while row:
    print("ID=%d, Name=%s" % (row[0], row[1]))
    row = cursor.fetchone()
 
conn.close()
 
 
cs

 

 

  샘플 코드의 동작을 확인 하기 위해 일단 다른 코드를 더 추가하지 말고, 해당 코드 그대로 현재 환경과 맟추어서 값을 조정해 넣어본다. where 조건은 없으므로, cursor.execute 의 뒷부분은(Jone Doe) 빼도 될듯 하다. 지금 만든 환경에 맞추면 아래와 같다. 맨위의 uft-8 이 부분은 한글 주석을 위해서 에러가 안 나도록 추가했다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# -*- coding: utf-8 -*-
# 모듈 호출
import pymssql
# DB에 연결함
conn = pymssql.connect(server='localhost', user='pyuser', password='test1234', database='mytest')
# 커서를 만듬
cursor = conn.cursor()
# 커서에 쿼리를 얻어서 실행 시킴
cursor.execute('SELECT Itemno, Category, FoodName, Company, Price FROM supermarket(nolock);')
# 한 행을 가져옴
row = cursor.fetchone()
# 행이 존재할 때까지, 하나씩 행을 증가시키면서 1번째 컬럼을 숫자 2째번 컬럼을 문자로 출력함
while row:
    print("ID=%d, Name=%s" % (row[0], row[1]))
    row = cursor.fetchone()
#연결을 닫음
conn.close()
cs

 

    c:\python\code 디렉토리에 sql_sample.py 이름으로 저장후 실행 시키면 아래와 같은 결과가 나온다. (저장하고 실행하는 부분을 잘 모르겠으면 2교시 때 스크린샷과 함께 자세히 설명했었던 부분들을 다시 참고 한다)

c:\Python\code>python sql_sample.py
ID=1, Name=과자
ID=2, Name=음료수
ID=3, Name=음료수
ID=4, Name=과자

 

 

  그럼 c와 같이 % 로 타입을 지정해 출력하는게 조금 귀찮은 듯해서 소스에서 아래 print 부분만 조금 바꾸어 + 기호를 이용해 결합해 전체 컬럼을 스페이스로 구분된 문자열로 출력해 보자.

1
print (row[0+ " " + row[1+ " " + row[2+ " "  + row[3+ " " + row[4])
cs

 

  근데 실행을 해보니 아래와 같이 에러가 난다. 에러 내용을 보니 첫 번째 itemno 컬럼은 숫자인 int 이고 Category 컬럼은 문자열 이라서, 숫자와 문자열을 합치려고 한다고 에러가 난다.

c:\Python\code>python sql_sample.py
Traceback (most recent call last):
  File "sql_sample.py", line 14, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

 

 

  아래와 같이 결과 컬럼을 str() 함수로 명시적으로 문자열 타입으로 변경하게 하면 에러가 나지 않는다. (구글에서 'python int to string' 이렇게 입력해 방법을 찾았다)

1
2
3
4
5
6
7
8
9
10
11
12
13
import pymssql
 
conn = pymssql.connect(server='localhost', user='pyuser', password='test1234', database='mytest')
 
cursor = conn.cursor()
cursor.execute('SELECT Itemno, Category, FoodName, Company, Price FROM supermarket(nolock);')
 
row = cursor.fetchone()
while row:
    print (str(row[0]) + " " + str(row[1]) + " " + str(row[2]) + " "  + str(row[3]) + " " + str(row[4]))
    row = cursor.fetchone()
 
conn.close()
cs

 

  다시 실행을 해보면 아래와 같이 최종 결과가 정상적으로 나온다.

 

 

  그럼 위의 코드를 나중에 전체 프로그램을 만들때 다시 사용하기 위해 킾해두고 파이썬에서 DB 호출을 해보는 4교시 시간을 마치려 한다. 다음 시간에는 2번째 요소인 암호화 모듈을 사용해 대상을 암복호화 하는 샘플을 만들어 보려한다. 여러 SQL 종류에 대해서 간단히 얘기하기로 했었는데 너무 글이 길어진 듯해서 6교시 퍼즐 조각들을 합쳐보기에서 언급 하려한다. (별로 깊이는 없으니 많은 기대는 하지 마시고...)

 

 

 

 

2017.2.19 by 자유로운설탕
cs

 

 

 

posted by 자유로운설탕
2017. 2. 13. 20:19 프로그래밍

 3 번째 시간이다. 이제 부터 전에 얘기했던 몇 개의 외부 환경을 사용하는 간단한 파이썬 프로그램들을 만들면서 구글을 통해 문제를 해결하는 예를 보이려고 한다. 이번 예제는 "DB에 암호화 할 평문 값 하나를 넣어놓고, 그 값을 불러와서 암호화 후 다시 복호화를 하고, 해당 값 들을 DB 로 다시 저장 후, 전체 값들을 가져와 화면에 표시"하려 한다. 이러한 부분을 나누어 해결하기(Divide and conquer) 방법을 사용하여 만들어 보자.

 

[목차]

0. 왜 파이썬 공부에 구글을 이용하는게 좋은가?

1. 언어를 바라보는 방법. 파이썬을 어떻게 바라봐야 할까?

2. 파이썬 설치와 환경, 버전 선택 하기의 이유.

3. 만들고자 하는 기능을 모르는 조각으로 나눠 조사해 보기

4. 데이터 베이스에서 내용 가져와 출력하기

5. 암호화 모듈을 이용해 암복호화 해보기

6. 퍼즐 조각들을 합쳐보기

7. 엑셀 파일 사용해 보기 -> 부록 : fuction 을 이용해서, 코드 정리해 보기

8. 정규표현식을 왜 사용해야 할까? 언어속의 미니 언어 정규표현식 살펴보기

9. 입력과 결과를 GUI 화면과 연결해 보기

10. Whois API 이용해 보기

11. 웹페이지 호출해 내용 파싱 하기(BeautifulSoup 그리고 한계)

12. 자동화 - 웹 자동화(with Selenium)

13. 자동화 - 윈도우즈 GUI 자동화(with pywinauto)

14. 자동화 - 작업 자동화

15. 수학 라이브러리 살펴보기

16. 그래픽 라이브러리 살펴보기

17. 머신러닝에서의 파이썬의 역활

18. 웹 프로그래밍 - Legacy Web

19. 웹 프로그래밍 - Flask 살펴보기(feat. d3.js)

20. 웹 프로그래밍 - Django 살펴보기

21. 정리 - 이런저런 이야기

 

 

 

  위에서 하려는 내용을 그림으로 표시하면 아래와 같다.

 

 

 

[문제 나누기]

  그럼 해당 문제를 풀려면 어떻게 해야 할까? 일단 자신이 모르는게 뭔지 정리해야 한다. 해당 문제를 구현하려면 아래와 같은 부분들이 필요하다.

1) 우선 SQL 에서 데이터를 불러오고 저장하는(정확하게 여기서는 업데이트 하는) 방법을 알아야 한다. (적절한 Database 를 설치해야 하고, 해당 Database 에 맞는 SQL 문을 만들어야 한다.)

2) AES256 방식을 사용해 불러온 값을 암, 복호화 해야 하다.

3) 최종으로 디비에 저장된 값 들을 가져와 cmd 화면에 출력해야 한다.

 

 

  일단 SQL 에서 데이터를 불러오고 저장하는 방법을 알아보자. 일반적으로 리눅스에서 돌아가는 MySQL 이 예제로 많이 사용되지만, 윈도우와 제일 친숙하고, 개인적으로 제일 익숙한 MSSQL 을 기준으로 구현을 하도록 하려한다. 나중에 해당 코드를 MySQL 과 Oracle 로 어떻게 변환 할수 있느냐에 대한 예제도 다루어 보려고 한다. MSSQL 은 유료 Database 가 아니냐고 얘기할 수도 있지만, MS 도 많이 개방 적이 되어서 소규모로는 기능제한이 거의 없는 express 버전을 제공한다(이 부분은 오라클도 마찬가지다). 그럼 MSSQL 연결을 지원하는 모듈을 찾기위해 구글에서 'python 3 mssql' 이라고 검색해 본다. 스택 오버플로우 글을 보면 pyodbc 와 pymssql 을 사용하라는 2개의 제안이 보인다.

http://stackoverflow.com/questions/17411362/connecting-python-3-3-to-microsoft-sql-server-2008

http://stackoverflow.com/questions/33326023/python-3-5-using-pymssql

 

  ODBC(Open DataBase Connectivity) 란 mssql, mysql, oracle 등 여러 db 에 대한 호출을, 각 databse 회사에서 윈도우에 지원하는 공통된 드라이버(뭐 API 가 정확한 표현이겠지만)을 통해서, 사용하는 개념이다. 비디오 카드 종류가 틀리더라도, 윈도우 드라이버가 잡히면 프로그램은 비디오 카드 종류만 세팅하면, 공통된 코드로 해당 비디오 카드들을 사용할 수 있는 것과 같은 개념이다. 전문 적인 설명은 아래의 링크를 참고한다.

http://dumaclub.tistory.com/entry/ODBC%EB%9E%80

 

 

  근데 ODBC 로 구현하게 되면, 아래와 같이 ODBC 세팅하는 방법도 소개해야 하고, 그럼 코드와 DB에 연결하는 계정 문자열이 분리되게 되어서, 설명하기가 더 어려워 지기 때문에, ODBC 방식이 아닌 직접 연결을 하는 라이브러리로 설명하려 한다. (사실 연결 방식은 ODBC 든 아니든 연결 계정이 노출된다는 면에서는 보안적으로는 바람직하진 못하다) 그래서 pymssql 모듈을 사용하기로 결정 한다. odbc 를 사용해 본적 없는 심심하신 분은 나중에 pyodbc 모듈을 이용해 구현해 보심 좋을듯 하다.

http://blog.danggun.net/1003

 

 

  2 번째로, aes256으로 암, 복호화 하기 위한 모듈을 찾아보자. 구글에서 'python 3 aes256' 로 찾으면 처음에 스택오버플로우 글이 나오고, 두번째로 우리나라 분이 정리한 문서가 하나 나온다.

http://blog.dokenzy.com/archives/1997

 

  읽어보니 파이썬 3.4에서 돌아간다고 하고, 스택오퍼플로우 글들을 참고해서 만든 코드를 테스트 하는 코드까지 추가되어 자세히 만들어져 있기 때문에 가져다 사용하기 적절해 보인다. 물론 실제로 필요한 프로그램을 만들때는 암호화 라이브러리 같은 경우, 샘플 코드가 인자 값들을 적절하게 세팅하여 사용했는지를 따져보고, 해당 라이브러리가 취약점이 없고 계속 유지보수 되고 있는 지를 따져봐야 할 거이다. 하지만 지금은 학습을 위해 프로그램을 만들고 있는 중이기 때문에, 특별한 문제는 없다고 가정하고 가져와 사용하기로 한다.

 

 

  3 번째는 가져온 내용을 프린트 하는 부분으로 문법 문제와 같지만 DB 에서 가져온 내용을 프린트 하는 부분이므로, DB 조회 샘플을 찾다보면 자연 스럽게 같이 해결 날것 같다.

 

 

 

[여담 - 문법 공부하기]

  여담이지만 개인적인 의견인데, 어떤 언어를 퀵하게 참조해서 사용해야 할때는(예전에 상용 자동화 솔루션을 사용하기 위해 공부 할 때 그랬었다), 메뉴얼이 어느정도 잘 정리되어 있다면 목차위주로 훝으면서 보게되면 언어가 지원하는 기능의 범위를 대충 알수 있게 된다. 예를 들어 파이썬 문법을 훝어 보기 위해서 구글에 'python 3 manual' 을 쳐서 나온 아래의 tutorial 을 한번 관심 있는 항목을 하나씩 예문 위주로 보는 것도 나쁘지 않다. 혹시 지금의 진행이 너무 구현위주로 빠져있어서 중요한 문법 요소들을 놓치는 기분이 들어 불안한 경우 아래 튜토리얼은 꼼꼼히, 나머지 레퍼런스는 대충 함 보셔도 괜찮을 듯하다. (절대 자세히 읽으라는 말은 아니고, 전체적인 흐름 파악 측면에서 보았음 한다.)

https://docs.python.org/3/tutorial/

https://docs.python.org/3/library/index.html

https://docs.python.org/3/reference/index.html

 

 

  그럼 여기서 글을 마무리 하고, 다음 시간에는 mssql 을 설치해서 계정, 테이블 등을 세팅 하고, pymssql 을 사용해서 DB를 조회하는 내용을 다루려고 한다. 그러면서 database 간의 차이에 대한 짧은 지식도 교양 차원에서 얘기하려 한다.

 

 

2017.2.13 by 자유로운설탕
cs

 

 

posted by 자유로운설탕
2017. 2. 8. 21:54 프로그래밍

  두번째 시간이다. 이번엔 파이썬 버전을 선택하는 문제에 대해서 얘기를 해보고 해당 파이썬 버전 및, 실습 환경을 선택한 이유에 대해서 설명 후, 실제 파이썬을 설치하고, 1교시에 나왔던 각 언어요소별 샘플 파일들을 실행해 결과를 보려한다.

 

목차

0. 왜 파이썬 공부에 구글을 이용하는게 좋은가?

1. 언어를 바라보는 방법. 파이썬을 어떻게 바라봐야 할까?

2. 파이썬 설치와 환경, 버전 선택 하기의 이유.

3. 만들고자 하는 기능을 모르는 조각으로 나눠 조사해 보기

4. 데이터 베이스에서 내용 가져와 출력하기

5. 암호화 모듈을 이용해 암복호화 해보기

6. 퍼즐 조각들을 합쳐보기

7. 엑셀 파일 사용해 보기 -> 부록 : fuction 을 이용해서, 코드 정리해 보기

8. 정규표현식을 왜 사용해야 할까? 언어속의 미니 언어 정규표현식 살펴보기

9. 입력과 결과를 GUI 화면과 연결해 보기

10. Whois API 이용해 보기

11. 웹페이지 호출해 내용 파싱 하기(BeautifulSoup 그리고 한계)

12. 자동화 - 웹 자동화(with Selenium)

13. 자동화 - 윈도우즈 GUI 자동화(with pywinauto)

14. 자동화 - 작업 자동화

15. 수학 라이브러리 살펴보기

16. 그래픽 라이브러리 살펴보기

17. 머신러닝에서의 파이썬의 역활

18. 웹 프로그래밍 - Legacy Web

19. 웹 프로그래밍 - Flask 살펴보기(feat. d3.js)

20. 웹 프로그래밍 - Django 살펴보기

21. 정리 - 이런저런 이야기

 

 

 

 

[들어가면서]

  우선 시작에 앞서 처음 프로그램 언어 공부하는게 왜 어려울까에 대한 얘기를 잠시하려 한다. 

 

  "A씨는 php 로 웹 프로그래밍 공부를 시작한다. 책에 나온 문법을 열심히 따라하는데 갑자기 html 이라는 조금 아는 언어가 끼어든다. 테이블을 출력하고, form 을 던지고 하더니, 조금 더 나아가니 db(database) 라는 녀석이 출현을 해서 php 에서 데이터를 저장하고 조회하고 한다. db를 잘 이용하려면 SQL 이라는 언어를 잘 알아야 한다고 한다. 뭔가 동적으로 움직이는 페이지를 만드려면 자바스크립트 라는 또 다르게 생긴 언어도 필요하단다. referer 얘기가 나오면서 http 헤더 얘기도 나오고, get, post 등등이 나오며 점점 내용이 복잡해 진다. html 과 비슷하게 생긴 xml 이라는 언어는 왜 또 책 뒷부분에 찜찜하게 스쳐가듯 언급되는지... 샘플을 그대로 보고 입력해서 실행하는데 에러는 계속 나고, 에러메시지는 이해가 잘 안가서 어떻게 해결하는지도 잘 모르겠다. php 는 참 어려운 언어같다. 남들은 웹프로그램이 제일 쉽다고 하던데 언어하나 배우는게 왜 이렇게 어려운가 싶다."

 

  위의 경험은 처음에 이런저런 언어를 공부한다고 책을 이것저것 잡히는 대로 볼때 마찬가지로 경험했던 현상이다. 첨엔 뭔가 잘 알것 같은 분위기 였는데, 진행하면 할수록 오리무중에 빠져버린다. 그런데 찬찬히 따져보면, 우리가 어려워 하는건 php 언어가 아니다. 언어는 한 측면에서 보면 껍데기에 불과할 수도 있다. php 를 배우면서 평생 처음 보는(또는 불완전하게 아는) db 에 쿼리를 던지는 것은, 말을 막 배우기 시작한 애들이 철학을 논하는 거랑 비슷한 상황이 된다. 중요한 것은 말을 배우는게 어려운게 아니라는 거다. 철학을 이해하지도 못하면서 그 말로 표현하려는게 문제지 말이다. (물론 말 배우는 건 어렵긴 하다;)

 

  프로그래밍 언어는 혼자서 움직이는게 아니라 미리 만들어졌거나 근간이 되는 여러 다른 언어와 시스템 들을 사용한다. 컴퓨터 화면(GUI), 디렉토리, 파일, database, http protocol, javascript, css, ajax, json, xml, 정규식, ftp, webserver, 메모리, 레지스터, 이미지 등등, 게다가 수학 및 물리학 같은 여러 도메인 지식을 포함한 그 밖의 많은 것과 함께 말이다. 그러다 보니 첨에 프로그래밍을 공부하다보면 언어의 본질적인 어려움이 아닌 언어가 접근하고자 하는 대상을 이해 못해 막힐수 밖에 없다. 그렇다고 문법만 공부하면 영원히 현실적인 주제들과 유리되어 버리고, 너무 현실적인 예제로 공부하게 되면, 기초 지식의 부족으로 쉽게 진도가 안나가고 지치게 되버린다. 아님 어찌어찌하게 따라가 마무리를 했더라도 조금 지나게 되면 뭘 했는지도 기억이 가물가물한 허무한 상태가 된다.(물론 형상화 되진 않았지만 작은 경험치가 쌓이긴 한다) 

 

  결과적으로는 적절한 문법 난이도와, 위에 언급한 한 두가지의 외부 접점을 연결시켜 공부하는게 바람직한 방법 같다고 생각한다. 그 배경하에서 왜 해당 언어의 각 문법 요소들이 굳이 언어에 존재해야만 하는지에 대한 필요성을 차근히 느낀다면 단지 외우는 프로그래밍이 아닌 인지하는 프로그래밍이 될 듯하다. 어떤 분야건 중요한건 스스로 마음속에 배우려는 대상에 대해 어떤 모델을 구축해 이해하느냐 이다. 어떤 측면에선 문법은 상세히 몰라도 괜찮다. 구글을 통해서 얼마든 문법은 찾아 이해해 적용하면 된다. 요는 문법 보다는 why? 이다. 책을 고를때도 그런 책을 잘 골라보는 게 좋다. 반대로 얘기하면 한 언어에 국한되더라도 저런 연결된 주제들을 적절한 깊이로 잘 이해한다면 다른 언어에 접근할 때 이미 아는 주제를 어떻게 이용하는가에만 집중할 수 있어 편하게 된다. 어차피 이용하는 방식은 고급언어로 갈수록 비슷해지니까 말이다. 마지막으로 막다른 길에 다달았을때 해당 부분에 대해서 힌트를 제공해 줄수 있는 사람이 있다면 더 좋을 건 없을 듯하다.

 

  사실 이 부분은 프로그래밍 뿐만 아니라 보안이나 테스팅 등 다른 분야를 공부할 때도 마찬가지인 부분 같다. 또 다른 예를 들자면 하둡 같은 빅데이터관련 시스템이나, 머신런닝을 배우고 싶어하는 분들이 리눅스의 기본적인 개념들에 대해서 모르고 있다면 아마 리눅스 서버에 프로그램 세팅하는 순간 부터 이해 안가는 개념들(사용자별 권한, ssh 설정, 환경변수, 모듈 설치, 서버간 동기화, 각종 디렉토리 파일 관련 명령어) 때문에 헤메느라 정작 실제 원했던 하둡 운영에 대해서는 쉽게 다가가지 못하게 될 가능성이 높을 것이다.

 

 

 

[파이썬 2.x vs 3.x 사이의 선택]

  파이썬 공부를 시작하면서 제일 먼저 고민한 부분은 버전 선택이다. 구글에서 "python download" 로 검색해서, 들어가는 파이썬 홈 페이지에서 제일 먼저 보는것이 2.x 대 버전과, 3.x 대 버전의 두개의 다운로드 링크 이다. 현재 기준으로 3.6과 2.7.13 버전이 나타난다.

https://www.python.org/downloads/

 

 밑에 박스 친 링크를 보면 어떤 버전을 선택할지 모르는 사람들을 위해서, 두 개의 버전을 비교한 링크가 있다. 앞으로 적은 부분에 대해 스스로 객관적인 판단을 하기위해 위의 링크의 비교 글을 한번은 살짝 읽어보길 바라며, "파이썬 2 3 선택" 으로 찾은 2개의 한글 페이지들을 소개해 본다.

https://b.ssut.me/python%ec%9d%98-%eb%af%b8%eb%9e%98-python-3%ec%9c%bc%eb%a1%9c-%eb%84%98%ec%96%b4%ea%b0%80%ea%b8%b0/

https://kldp.org/node/129183 

 

  우선 파이썬 2를 옹호하는 사람들은 현재 많은 회사에서 파이썬 2 기준으로 프로그램들이 개발되어 있어 실제 일을 할때 현실적인 버전이고, 외부 모듈들도 대부분 2 는 완벽히 지원하지만, 3 는 지원 안하거나 미지원 되는 모듈들이 많고(이 부분은 정확히 얘기하면 2를 지원하는 모듈들이 더 이상 3를 미지원 하는 문제일 것이다. 코드를 변경할 수고만 감당한다면 같은 기능을 가진 파이썬 3용 새로운 모듈들로 대체될수 있는 가능성도 있다고 본다), 성능 측면이나, 개발과 관련된 기술 문서를 웹에서 찾는데 불리하다는 얘기이다. 파이썬 3를 옹호하는 사람은 파이썬 2는 2020년에 지원이 만료된다는 예정이 있고, 2에서 구조적으로 개선된 여러 언어기능이 파이썬 3에는 있지만, 2는 앞으로 유지보수 정도 수준으로만 개선될 예정이기 때문에 3로 가는게 맞다는 것이다.(아마 파이썬 3의 모듈 호환 문제 같은 경우는 점점 개선될 거 같긴 하다)

 

  저도 원래 시작은 2.7로 시작했다. 근데 mssql db 에서 한글로 된 내용을 가져와 cmd 화면에 표현하려 했는데, 아래와 같이 한글 출력 부분에서 유니코드 변환 에러가 났다.

  구글링을 해서 아래 utf-8 관련 코드를 상단에 추가해서 위의 인코딩 에러는 안났는데, 이후엔 아래와 같이 한글이 깨져보인다.

# -*- coding: utf-8 -*-
import sys
reload(sys)

sys.setdefaultencoding('utf-8')

 

  또 구글링을 해보니 한글 윈도우 cmd 창의 디폴트 코드 페이지가 cp949 라서 그렇다고 해서 아래 명령어를 통해서 cmd 창의 코드 페이지를 utf-8로 변경해 봤다.

>> chcp 65001

 

  이후 다시 샘플을 실행해 보면 아래와 같이 정상적으로 나오긴 한다.

  이렇게 한바탕 헤메며 진을 빼고나서 보니 mssql 등 db와 연동 했을때 파이썬 2 버전의 한글 처리에 대해서 명확하게 구글에 정리된 자료는 없는 듯도 하다.(물론 잘 정리되어 있는데 유니코드 및 한글 인코딩 구조에 대해 까막눈이라서 못 찾았을 수도 있다--;) 그런데 이런 인코딩 오류 부분은 서양 언어가 아닌 동양 언어 국가의 비애인데, 대부분의 프로그래밍 언어나 라이브러리, 유틸리티들이 처음 시작 될때는, 한글, 한자 같이 2byte 언어를 고려한 유니코드 대응 설계를 하지 않는다는 것이다.  많이 유명해지고, 2byte 권 사용자들이 개발자에게 불만을 계속 토해내게 되야, 겨우 유니코드 반영이 되긴 하는데 이 시점이 보통 상당히 늦고, 그나마 불완전하게 땜빵 설계로 되는 경우도 종종 있는 듯 하다. 물론 데이터를 모두 영문으로만 쓰면 괜찮겠지만, 세상일이 어찌될지도 모르고 이렇게 한글이 나올때마다 처리에 신경 써야 되는 부분은 귀찮은 건 사실이다. 좀더 전문적인 파이썬 2.x 의 한글 처리에 대해서는 아래 글을 참고하자.

http://ifyourfriendishacker.tistory.com/5

 

  그래서, 3.x 대 버전을 설치 후 동일한 코드를 돌려봤는데(print 문법 차이 땜에 조금 바꾸긴 했다), 해피하게도 기본적으로 유니코드를 잘 지원해서 위에 언급된 유니코드 관련 코드들을 안 넣어도 한글이 정상적으로 cmd 창이나 엑셀 파일 등에 잘 출력된다. 그래서 주저 없이 파이썬 3를 사용해 학습하는 것을 선택하게 되었다.    

 

 

 

[산 넘어 산 - 학습을 위한 3.x 버전 선택]

  일단 3버전으로 하기로 한 후에도 다시 고민이 생기게 되었다. 최신 버전을 사용하느냐 약간 이전 버전으로 사용하느냐에 대한 문제 였다. 마이너 버전 끼리의 기능 차이는 별로 없을 가능성이 높은 상태에서 최신 버전의 가장 큰 문제는, 모듈 호환성 관련 문제 발생시 아무래도 구글에 참조할 만한 글들이 많지 않을 가능성이 높다. 또 모듈 설치시 편한 pip 명령어를 사용하려면 최신버전은 아무래도 모듈 호환성 업데이트가 안되있을 수 있어 좀 불리하다. 처음 시작하던 때에는 3.5.3 이 최신 이여서 이것저것 막히는 걸 해결하면서 왔는데, 현재는 3.6이 2016년 12월 중순에 나와있긴 했다. 그래도 최신으로 해야 되지 않을까 해서 몇 가지 모듈 테스트를 한 결과 3.5.3에서 잘 설치되는 모듈이 3.6에는 빌드에러가 나서 설치가 안되는 일이 발생했고, 구글에도 딱히 가이드 삼을 문서가 없어서 현 블로그에서 설명은 3.5.3 기준으로 진행하려 한다. 물론 2.x 과의 선택에서도 마찬가지 였지만, 지금 일어나는 호환성 문제는 세월이 지나면 모듈들이 업데이트 되면서 자연스럽게 해결 날 수도 있다.

 

 

 

[파이썬 3.5.3 설치]

  설치에 오기까지 잡담이 많이 길었지만 실제 선택하기 위해 고민한 과정을 보여주고 싶어 그런 것이라고 이해했으면 하고, 이제 버전도 정했으니 설치로 들어간다. 개인 환경은 윈도우즈 10 Home, 64비트 이다. 윈도우즈 7도 호환성은 거의 비슷한 것 같다.

 

  먼저 다운 로드를 받기 위해서 상단 다운로드 그림의 Python for windows 링크를 클릭 하거나, 구글에서 'python 3.5.3 download' 라고 쳐서 젤 처음인 아래 링크를 들어간다.

https://www.python.org/downloads/release/python-353/

  windows x86이 32비트 OS용이고, x86-64가 64비트 용이다. executable installer 가 우리가 보통 생각하는 exe 형태의 설치 파일이다. 저 같은 경우는 64비트이니 아래 파일을 다운 받았다.

Windows x86-64 executable installer

 

다운받은 다음에 실행해 보자

  'Add Python 3.5 to PATH' 를 체크하고, 설치 디렉토리를 정하기 위해서 'Customize installation' 을 클릭하자. path를 추가하는 이유는 어떤 경로에서든 python 명령어가 실행되게 하기 위해서 이다. 설치 디렉토리를 변경하는 이유는 cmd 창에서 다단계의 복잡한 디렉토리 경로로 찾아 들어가기 싫어서 이다^^; 혹 path 개념을 잘 모르신다면 아래의 링크를 참고하자.

http://dvjin.tistory.com/4

 

 

  두 번째 화면은 어차피 다 체크되 있으니 Next 를 그냥 누른다. 앞으로 우리가 자주 보게될 pip 를 설치하는 옵션이 있다.

 

 

  마지막으로 모든 사용자가 사용하도록 체크하고(어차피 혼자쓰는 컴퓨터일 테니), 경로를 c:\python 이라고 간단한게 바꿔주자(디렉토리가 없을테니 Browse 버튼 누르지 말고, 걍 텍스트 박스에서 수정하자). Install 버튼을 누르면 파이썬이 설치 완료될 것이다.

 

 

  그럼 실행을 해보기 전에, 메모장과 cmd창(도스창)에서 실행을 하라고 얘기하는게 왠지 구닥다리 방식 같아서, 구글로 'python ide' 라고 검색해 보니, visual studio 를 이용하는 방법, eclipse 를 이용하는 방법, 그리고 현재는 pycharm 이라는 툴이 많이 쓰이는 거 같다.(프리, 상용) 하지만 IDE 로 설명하게 되면 왠지 조금 더 복잡하게 될거 같기도 하고, 또 처음에는 IDE 를 사용 안하고 cmd 창에서 live 하게 실행해 보는 것도 구조 이해에 도움도 될거 같고(리눅스에서 실행하면 어차피 이런 모드기도 하다), 저도 현재는 텍스트 에디터에 cmd 화면을 이용해 사용하고 있는 형편이고 코드도 클래스니 구조화니 그런건 없어서 파일 하나면 되기 때문에, 예쁜 IDE 사용여부는 아래의 링크를 참고하고, 다른 블로그에도 많긴 하지만 나중 시간에 pycharm 이나 설치하고 사용하는 예를 들까 싶다. 

http://yaraba.tistory.com/173

http://cksl.tistory.com/31

http://noeticforce.com/best-python-ide-for-programmers-windows-and-mac

 

 

  그럼 윈도우즈 10에서 명령 프롬프트(관리자)를 실행 한다. (혹시 더 초보셔서 윈도우즈 10에서 명령 프롬프트 실행을 모르시면, 아래 링크를 참고 한다-좀 10이 이리저리 숨겨놓긴 한듯 하다;) http://slic.tistory.com/410 

  ※ 팁으로 만약 윈도우즈 10 UI 가 넘 화려해서 싫은 저 같은 분은 classic shell 이라는 프리웨어를 설치하시면 익숙한 7 스타일로 시작 메뉴 등을 사용할 수 있다. http://windwaker.net/2096

 

 cmd 창이 뜨면 python 이라고 친다. 아래 같은 특이한 프롬프트의 창이 뜨면 정상적으로 설치한 것이다.

ctrl+z 키를 누른 후 enter 키를 눌러서 원래의 도스창으로 돌아온다.

 

 

 

[샘플들 실행해 보기]

자 그럼 1교시 때 언급한 샘플 파일들을 하나씩 실행해 보자. 

먼저 변수 얘기할 때 만들었었던 친구들의 빵 갯수 더하기 코드를 보자

1
2
3
4
5
breadfriend = [23456]
 
breadfriend_sum = sum(breadfriend, 0.0)
 
print(breadfriend_sum);
cs

 

위의 내용을 복사하여 메모장에 붙여 넣어보자.  c:\python 폴더 밑에 코드들을 저장할 code 라는 디렉토리를 만들자. 메모장 내용을 저장 하면서 파일형식을 '모든 파일'(그래야 원하는 확장자로 저장된다), 이름을 breadcount.py 라고 만들어 놓은 code 라는 폴더에 저장한다. (첨 실행이라서 혹시나 해서 몰라서 아래 스크린샷을 추가한다. 담부터는 힘들어서 말로만 --;)

 

 

  이후 cmd 창에서 c:\python\code 창으로 이동한다. 이 부분도  첨이니까 기초부터 설명하고 스크린샷을 첨부한다. 

이동하는 방법은 처음 cmd 창이 뜨면 c:\windows\system32 폴더일 것이다. 여기서

1) cd / 후 enter(c:\ 로 가게된다)

2) cd python\code 후 enter 하게 되면 프롬프트가 c:\python\code 로 되어 있을 것이다.

(이 부분도 첨이자 마지막 스크린샷)

 

  자 첫코드가 실행되어서 다섯개의 빵의 합인 20이 나오게 되었다. 다시 한번 얘기하지만 지금 이 메모장과 도스창으로 하는 작업이 익숙하지 않다면, 프로그래밍 자체가 아닌 연결되어 있는 배경지식이 필요한 경우이다. 이 경우 가능한 바로 IDE 를 사용하지 말고 지금 하는 구식 방법을 조금 사용해 보는 것도 추천 한다. 헤메면서 얻은 지식은 잊혀지지 않기 때문이다.(단 코드가 복잡해지면 메모장은 한계가 있기 때문에 위의 링크에 추천한 IDE 나 문법을 칼라로 표시해 주는 선호하는 편집기를 쓰는게 낫다.)

 

 

  두번째 부터의 실행 코드 예제는 언어구조 개념에서 설명했던 예들의 코드들을 가져와 보자

 

  두번째 객체 예를 보이는 writefile.py 의 샘플은 아래와 같다.

 

1
2
= open('test.txt''w')
f.write("This is a test")
cs

 

  2줄인 엄청 간단한 코드로, 다른 언어를 하나라도 공부해 본 분들은 한번 쯤 파일 작업 할때 봤던 비슷한 코드 일 거다.(물론 옛날 언어에서는 조금 더 장황하게 써야했다). 코드를 설명하자면 test.txt 라는 이름을 가진 파일 객체를 write(w: 쓰기) 모드로 열어서, 그 안에 "This is a test" 라고 내용을 적는다. 저 open 이라는 명령이 파일 test.txt 라는 이름을 가진 파일 객체를 만든다는 모습을 보여주는 코드라고 생각해 6)번 샘플로 만들어 봤다.

 

  실행은 똑같이 메모장에 붙인 후 c:\python\code 테이블에 writefile.py 라고 저장 후, cmd 창의 해당 폴더에서 python writefile.py 입력 후 폴더안을 보면 "This is a test" 내용이 적힌 test.txt 파일이 생성되어 있을 거다.

 

 

  세번째는 함수 예를 보여주는 function_sample.py 이다.

1
2
3
4
5
6
7
8
def myfn(x):
    if x > 100:
        print("over 100")
    else:
        print("under 100")
        
myfn(120)
myfn(90)
cs

 

  자 파이썬 문법에 대해 공부한건 별로 없지만, 대충 보면 def myfn(x) : 부분으로 함수가 시작되고, 다른 언어에서 { ( 등으로 구분되던 부분은 아무래도 스페이스나 공백으로 구분 되는 듯 하다. 위의 예는 tab 으로 함수 안의 빈 공간을 채워놨다.

 

  예를 들어 밑에 처럼 앞의 if x > 100; 앞의 tab을 2개로 해서 else 와 tab 수를 다르게 한다면 아래와 같은 문법 에러가 난다. 번거로운 경계 문자들을 없앤 대신 만드는 사람이 로직에 맞게 들여쓰기(indentation)를 명확히 맞춰줘야 한다. 

 

1
2
3
4
5
6
7
8
def myfn(x):
        if x > 100:
        print("over 100")
    else:
        print("under 100")
        
myfn(120)
myfn(90)
cs

TabError: inconsistent use of tabs and spaces in indentation

 

위의 첫번째 정상 코드를 실행 하면, 정의한 함수 myfn 에 120 과 90의 값이 넘어가서, 각각 결과가 나오게 된다.  

C:\Python\code>python function_sample.py
over 100
under 100

 

 

  네번째 예는 클래스 내의 method 를 보여주는 upper_method.py 이다.

1
2
3
input = "This is a sample"
result = input.upper()
print(result)
cs

 

  고급언어로 갈수록 string 같이 단순한 문자열을 담는 기본 변수들도 클래스로 정의되어, 해당 변수에 담겨있는 데이터에 대해 클래스에 내장된 유용한 메쏘드를 사용할수 있게 한다. 위의 예에서 고전 언어 같은 경우는 upper 라는 따로 만든 함수에 input 문자열을 넘겨줬어야 했었을 테지만, 파이썬은 input 변수 자체가 upper 라는 메쏘드를 소유하고 있어 스스로 바로 변환을 한다.  

C:\Python\code>python upper_method.py
THIS IS A SAMPLE

 

 

  다섯번째 예는 내부 라이브러리(파이썬의 경우 모듈)을 사용하는 library_sample.py 예이다.

1
2
3
4
import statistics
 
data = [3746]
print (statistics.mean(data))
cs

 

  기본적으로 파이썬 기본 기능에서는 배열의 평균을 한번에 구할 수는 없다. 위에선 import 명령어를 이용하여 기본 통계(statistics) 모듈을 가져온 후, 통계 모듈안에 있는 mean 기능을 이용하여(statistics.mean(data)) 배열의 평균을 구해서 출력 한다. 실행 결과는 아래와 같다.

C:\Python\code>python library_sample.py
5

 

 

  마지막 예는 우리가 이제 것 cmd 창 화면으로만 사용했던 파이썬 기능을 우리가 쓰는 윈도우 창과 같은 GUI 화면에 표시해 주는 예이다. 실제 구현 예는 차후 보겠지만, 맛보기 샘플을 위해서 해야될 일도 적지는 않다. 우선 구글에서 어떤 gui 모듈을 사용할지를 판단해야 한다.

  구글에서 'python gui' 라고 검색을 하고 보다가, 아래의 글을 보게 되었다. 2015년도니 기간도 적당하고, 참고할만 한듯 하다.  

http://insights.dice.com/2014/11/26/5-top-python-guis-for-2015/

 

  이외에도 구글 상위순으로 이런 저런 글들을 보다 보면 제일 많이 나오는게 pyqt 와 wxpython 인거 같다. (너무 과거의 문서가 상위에 나오면 도구 옵션에서 날짜를 1년 정도로 제한하는 것도 좋다) 

 

  그럼 다시 구글에서 'wxpython vs pyqt' 라고 검색을 해보자. 나름 기술 적으로 활발한 토론이 이루어 지는 듯한 reddit.com(클리앙에서 아이폰 탈옥 관련할때 자주 언급되는 곳이다)의 2015년도 글을 하나 보자

https://www.reddit.com/r/learnpython/comments/3pif4k/tkinter_vs_pyqt_vs_wxpython/

 

  대충 보면 파이썬에서 기본제공하는 Tkinter 라는 기능은 배우긴 쉬운데 기능이 넘 단순하고 수동으로 해야되는 일이 많고, pyqt 는 제일 기능은 편하지만, 상업적으로 사용하기엔 라이센스 관계가 복잡하다고 한다(아니라는 댓글도 같이 달려 있다). wxpython 은 어중간 한 위치인가 보다. 일단 저는 어중간한 wxpython 을 선택하게 됬다. 어차피 gui 라이브러라는게 비슷비슷하기 때문에 하나를 감을 잡으면 다른 것들은 적당히 적응할 수 있을 것이라고 생각하고 말이다.(개인적으로 예전에 matlab이라는 언어에서 gui 라이브러리를 좋아해 이런저런 걸 만들었어서 조금은 더 익숙 할 것은 같다)

 

  그럼 python 에서 pip 를 이용해 wxpython 을 설치해 보도록 해보자. pip 는 윈도우의 프로그램 추가 삭제를 cmd 창으로 옮겨놓은 버전이라고 봐도 될듯하다. 리눅스의 apt-get, yum 같이 특정 프로그램을 해당 명령어를 이용해 설치하겠다고 정의하면 (아마) 의존성 까지 고려해서 한번에 설치하거나 삭제해 주는 프로그램 이다. 설치된 패키지는 python 폴더내의 tools 폴더안에 들어가게 된다.  https://ko.wikipedia.org/wiki/Pip

 

  일단 파이썬 3를 wxpython 이 지원할지 안할지 모르는 상태니, 구글에서 'python3 wxpython pip' 이라고 쳐보자. 그런데 첫번째 글을 읽어보니, wxpython 은 2.x 대만 지원하고 3.x 를 지원하기 위해서, wxpython Phoenix 이란거로 모듈이 분리되었다고 한다.

  http://stackoverflow.com/questions/28029760/wxpython-in-python-3-4-1

 

  스택오퍼플로어에 가이드 된데로 cmd 창에서 아래 명령어를 실행시킨다.

pip install -U --pre -f https://wxpython.org/Phoenix/snapshot-builds/ wxPython_Phoenix

 

 뭔가 한참 진행되더니 성공적으로 설치되었다고 뜬다. happy case 다.

Installing collected packages: six, wxPython-Phoenix
Successfully installed six-1.10.0 wxPython-Phoenix-3.0.3.dev2812+b3485d4

 

  그럼 이제 GUI 창을 맛보기로 띄워주는 wx_sample.py 내용을 보자

1
2
3
4
5
6
7
8
9
import wx
 
app = wx.App()
 
window = wx.Frame(None, title = "wxPython Frame", size = (300,200)) 
panel = wx.Panel(window) 
label = wx.StaticText(panel, label = "Hello World", pos = (100,50)) 
window.Show(True) 
app.MainLoop()
cs

 

  얘는 어쩔 수 없이 코드가 조금 길다. 간단히 설명하면 저 복잡한 구조는 우리가 매일 쓰는 윈도우 어플리케이션의 구조와 연관되어 있다. 설치한 wxPython 라이브러리를 가져오고(import wx )-> 어플리케이션 객체를 하나 만든다(ws.App)-> 어플리케이션 객체안에 작은 윈도우를 하나 만들고(wx.Frame)-> 윈도우 창에 넣을 판데기 공간(패널)을 하나 만든다(wx.Panel)->  패널안에 넣을 Hello World 텍스트를 하나 넣고(wx.StaticText)-> 윈도우를 우리한테 보여준다(window.show)-> 이후 이벤트를 수령해 사용자 동작에 반응한다(app.MainLoop).

<google: 'wxpython app mainloop' 참고>

 

  실행을 하면 아래와 같이 Hello World 가 가운데 있는 작은 윈도우 창을 보여준다.

C:\Python\code>python wx_sample.py

 

 

  이렇게 해서 또 생각보다 길어진 2교시가 끝났다. 다음 시간에는 만들어 보고자 하는 기능을 하나 정하고 어떻게 구글을 이용해 해당 기능을 나누어 조사하여 원하는 기능을 만들지에 대한 부분을 진행할 예정이다.

 

 

[추가]

파이썬 3.7의 경우는 pip install wxpython 으로 설치하면 됩니다^^

 

 

2017.2.12 by 자유로운설탕
cs

 

 

posted by 자유로운설탕
prev 1 ··· 4 5 6 7 8 9 next