2019년 12월 19일 목요일

파이썬 with 구문 ( Context manager 사용 방법)

이 방법은 아마도 python 2.5에서  추가된 기능입니다.

with~as 구문을 사용하는 방법인데, 이게 아마도 고대의 유물인 Lisp 같은 언어에서는 쓰는 매크로 형태와 비슷한 구문입니다.  (with-open-file 같은 구문)

with open('filename.txt','w') as f:
  blabla.. 


대략 이런식으로 사용합니다.

기존에 file processing을 하는 경우 open -> context -> close 형태로 사용하고,
이중에 file open 이 fail 되었을 경우 등등 예외처리를 해주었는데,

아무래도 실제 본질 보다는 파일 access이런게 제대로 되었는지에
신경을 쓸 수 밖에 없고 이런부분이, 생각의 흐름을 방해하는 요소중의 하나였는데

이 context manager를 사용하는 경우,
이런 예외처리 부분들이나,  with로 ,, 생각의 흐름을 방해하지 않게,
 상당히 간략하게 표현이 됩니다.

또 이런 부분들이, 아래와 같이,,
__enter__ ,
__exit__ (self, type, value, traceback)  # 예외 발생시 처리 하는 인자들,


함수들을 override하여서, 아래와같이 class안에서 구현이 가능하기도 하고,






class Logger(object):
  __enter__(self):
    ''' enter process '''
  __exit__(self, type, value, traceback):
    ''' exit process '''



아래와 같이 단순 function에 decorator 형태로 @contextmanager 를 함수위에 추가하여
context manager를 추가할 수 도 있습니다.


@contextmanager
def log:
  try:
    ''' log file open and process '''
  finally:
    ''' log file close process ''' 



이 with 구문의 사용은 주로 file ,socket, db  access 라든지 login process 등등에서 활용이 가능하고, 이 with 구문의 활용은 사실 무궁무진합니다

그렇지만 그중에서도 결국 가장 많이 사용하는 부분은 File I/O에서 일텐데,

이중에 동시에 파일을 열고 닫는 경우은 아래와 같은식으로도 사용이 가능합니다
예를 들면,

with open("file1", "r") as src:     
  with open("file2", "w") as dst:         
    dst.write(src.read())


이렇게 사용할 수도 있지만, 위와 같이 동시에 사용하는 것 보다는
아래와 같이 하나의 statement로 묶는 것이 좀더 간결해보입니다.


with open("file1", "r") as src, open("file2", "w") as dst:
  dst.write(src.read())

즉. 위와 같은 한 문장으로 동시에 여는 형태로 사용할 수도 있습니다.



2019년 12월 14일 토요일

파이썬, for ... else .. 사용법


파이썬에는 for문에 특이한 else기능이 하나 더 있습니다.

이것은 일종의 syntax sugar같은 것인데,

이런 문법들을 사용하면, 간결해지면서 가독성이 좋아지죠,,
(단 문법을 알고 있다는 전제로 입니다. )

이 방법의 사용예는

for문을 사용하다보면, 루프 중간에 break 문으로 빠져나오는 경우들이 있는데,
이게 break문이 걸려서 빠져나가는지 아닌지를 판단이 필요한 경우가 있습니다.

보통은  flag등을 둬서, 처리하는게 기존의 방식이라면,
for문과 같은 레벨에 else를 둬서 break없이 빠져나온 경우를 처리하는 방법입니다.




for x in range(4):
  if x == 2:
    print ('loop out')
    break
else:
  print ('loop end')



위 예제의 경우는 x =2 에서 루프를 빠져나오기때문에, else문이 실행이 되지 않고
'loop out' 이 출력이 되고,



for x in range(4):
  # nop
  pass
else:
  print ('loop end')


위와 같은 경우는 , for loop가 break없이 빠져나왔으므로 'loop end' 가 출력이 된다.




2019년 12월 12일 목요일

파이썬, ==, is 의 차이





  • == 는 값을 비교 한다. 실제로 값을 비교해서 같은지 return을 돌려줌
  • is 는 reference를 비교한다. 두개가 같은 object인지를 비교함.   



그래서, is  로 비교하는 것은 object들을 비교할때는 유용하나,

== 으로 비교하는 것과 결과가 다를 수 있다.




a = [1,2,3]
b = a 
b is a # True
b == a # True

b = a[:] # slice operator로 다시 list를 생성
b is a  # False, 다른 object
b == a  # True, 다른 object이나 값이 같음. 
https://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is?rq=1

2019년 12월 10일 화요일

파이썬 정규식 regex Grouping



Grouping

정규식에서 ( )괄호는 그룹을 이야기합니다.
이 Grouping은 꽤 유용한 방법중의 하나입니다.

각각의 매칭을 MatchObject로 넘기며, 크게 아래와 같은 두가지 방법이 있습니다.

  1. 순서대로 가져오는 방법 
  2. 이름을 지정해서 가져 오는 방법


Ordered Group

이 중 순서대로 가져오는 방법은 group(0) : 전체,
group(1) : 첫번째 괄호
group(2) : 두번째 괄호
이런식으로 전개할 수 있으며, 아래와 같이 전화번호 같은 것을 매칭을 할떄,
아래와 같은 형태로 매칭이 됩니다.


import re
p = re.compile('([\d]+)_([\d]+)')
m = p.search('345-1234')
m.group(0) # 345-1234
m.group(1) # 345
m.group(2) # 1234




Named Groups

이름에 매핑하는 방법은, 아래와 같이 작성해서, dictionary로 반환을 받는 방법입니다.
(?P<name>pattern)


import re
p = re.compile('(?P[\d]+)_(?P[\d]+)')
m = p.search('345-1234')
m.group(0) # 345-1234
m['first'] # 345
m['second'] # 1234

정규식에서 다시 값을 추출해서 특정 용도로 사용할때 , 중간단계를 사라지게 해서
편한 방법중 하나 입니다.


Back references 

back referencing(역참조)의 \1은 처음 사용한 표현식과 일치한다는 이야기입니다.
마찬가지로 \2, \3은 두번째 세번째 사용한 표현식과 일치한다는 것이고,
이 것은 주로 패턴이 반복되어서 나올때에 사용합니다

그리고, substitute (치환)을 할때, 매칭을 다시 가져다 쓸 때 사용합니다.
주로 언제 사용하냐면 순서를 바꿀때, 예를 들면, 첫번째 매칭이랑 두번째 매칭을 순서를 바꿀때, 이 방법이 유용합니다.

import re
p = re.compile('(?P[\d]+)_(?P[\d]+)')
m = p.sub('P\2_M\1','345-1234')
m # P1234_M345




2019년 8월 17일 토요일

Python Asyncio 와 Threading, 그리고 multiprocessing


동시에 여러가지 일들을 처리하는 방법에는 여러가지가 있다.

파이썬에서는 3가지 정도 방법을 제시하고 있다.

첫번째는 thread, thread는 process를 새로 만드는것이 아니라 하나의 process안에서
time sharing을 하면서, 동시에 여러작업을 처리하는 것이다.

하지만, python에서는 GIL이라는 방식때문에, 이 thread가 완벽하게 제대로 일을 처리를 하지 못하는 문제가 있다.

그래서 두번째 multiprocessing을 한동안 쓰라고들 이야기가 돌았는데,
processing은 새로운 process를 만드는 것이다. 이것은 하나의 process에서 처리하는 것이 아니라, 아예 OS로부터 새로운 process를 할당받아서, 처리를 하는 것인데,
process를 새로 만들다보니, 앞뒤로 오버헤드가 붙는다.

이 경우는 GIL의 영향성을 받지는 않는데, 아무래도 새로 context를 생성하고 하는 작업때문에 다량의 프로세스를 만들때는 느려질 수 밖에 없다.

그래서 마지막으로 async, 이건 thread랑 비슷하긴한데, 조금 더 특이하다,
GIL이라는 것의 제약을 덜받기 위해서 IO bound job에서만 제어권을 넘기는 방법이다. 

실제 프로그램을 뜯어봤을때 시간을 잡아먹는 부분이
두종류가 있는데 하나는 CPU, 많은 연산량을 필요로 하는 부분이 있고
다른 하나는 I/O bound, I/O를 하면서 시간을 많이 잡아먹는 부분이 있다보니
이중에서 I/O access하는 동안에 cpu로 처리할 것을 처리할 수 있게 한것이 async io방식이다.

그럼 이중에 어떤것을 써야 가장 좋은가?? 라는 의문이 생기는데.

cpu bound에서는 multiprocessing이 좋고,
i/o bound에서는 , thread와 asyncio가 좋다는 결론이 나온다.

그럼 thread와 asyncio는 ??
asyncio가 대량의 처리를 하는데 유리하다고 한다,

결론은, asyncio가 요즘 유행하는 기법이긴하나,
상황에 맞게 쓰는 것이 낫다...