"프로그래밍 언어의 개념과 흐름에 대한 고찰 - 파이썬답게 코딩하기" 학습중...


동시성과 관련한 thread 기법에 대해 어렴풋이 알거나 몰랐던 내용들 몇가지 정리해봅니다.



Thread Event


# ## Thread Event
# import time
# import logging
# import threading
#
# logging.basicConfig(level = logging.DEBUG, format = "(%(threadName)s) %(message)s")
#
# # >>> e = threading.Event()
# # >>> e.isSet()
# # False
# # >>> e.set()
# # >>> e.isSet()
# # True
# # >>> e.clear()
# # >>> e.isSet()
# # False
#
# def first_wait(e1, e2) :
# while not e1.isSet() :
# event = e1.wait(1)
# logging.debug("Event Status : (%s)", event) ## logging에서 message 출력 부분
#
# if event :
# logging.debug("e1 is set.")
# time.sleep(3)
# logging.debug("Set e2")
# e2.set()
#
# def second_wait(e2) :
# while not e2.isSet() :
# event = e2.wait(1)
# logging.debug("Event Status : (%s)", event) ## logging에서 message 출력 부분
#
# if event :
# logging.debug("e2 is set.")
#
# def main() :
# e1 = threading.Event()
# e2 = threading.Event()
#
# t1 = threading.Thread(name = 'first', target = first_wait, args = (e1, e2)) ## logging에서 threadName = name = first
# t1.start()
#
# t2 = threading.Thread(name = 'second', target = second_wait, args = (e2,))
# t2.start()
#
# logging.debug("wait...")
# time.sleep(5)
# logging.debug("Set e1")
# e1.set()
# time.sleep(5)
# logging.debug("exit")
#
# if __name__ =="__main__" :
# main()

# (MainThread) wait...
# (second) Event Status : (False)
# (first) Event Status : (False)
# (first) Event Status : (False)
# (second) Event Status : (False)
# (second) Event Status : (False)
# (first) Event Status : (False)
# (second) Event Status : (False)
# (first) Event Status : (False)
# (MainThread) Set e1
# (first) Event Status : (True)
# (first) e1 is set.
# (second) Event Status : (False)
# (second) Event Status : (False)
# (second) Event Status : (False)
# (first) Set e2
# (second) Event Status : (True)
# (second) e2 is set.
# (MainThread) exit




Thread Lock


## Thread Lock

# import time
# import logging
# import threading
#
# logging.basicConfig(level = logging.DEBUG, format = "(%(threadName)s) %(message)s")
#
# def blocking_lock(lock) :
# logging.debug("start blocking lock")
#
# while True :
# time.sleep(1)
# lock.acquire() ## .acquire() 메서드가 lock을 잡기 위한 메서드인데 아무런 인자값을 주지 않으면 잡을 때까지 block.
# try :
# logging.debug("grab it")
# time.sleep(0.5)
# finally :
# logging.debug("release")
# lock.release()
#
# # python threading 패키지에서는 Lock을 지원한다.
# # lock acquire하면 해당 쓰레드만 공유 데이터에 접근할 수 있고,
# # lock release 해야 다른 쓰레드에서 공유 데이터에 접근할 수 있다.
#
# def nonblocking_lock(lock) :
# logging.debug("start nonblocking lock")
# attempt = 0
# grab = 0
# while grab < 3 :
# time.sleep(1)
# logging.debug("attempt")
# success = lock.acquire(False) ## acquire 인자로 False를 전달하여 이 쓰레드는 block되지 않고 다음 로직을 수행.
# try :
# attempt += 1
# if success : ## acquire를 하게 되면 True를 반환하여 이하 구문을 실행.
# logging.debug("grab it")
# grab += 1
# finally :
# if success :
# logging.debug("release")
# lock.release()
#
# logging.debug("attempt : %s, grab : %s" % (attempt, grab))
#
# def main():
# lock = threading.Lock()
# blocking = threading.Thread(target = blocking_lock, name = "blocking", args = (lock,))
# blocking.setDaemon(True)
# blocking.start()
#
# nonblocking = threading.Thread(target = nonblocking_lock, name = "nonblocking", args = (lock,))
# nonblocking.start()
#
# if __name__ == "__main__" :
# main()
#
# # (blocking) start blocking lock
# # (nonblocking) start nonblocking lock
# # (nonblocking) attempt
# # (blocking) grab it
# # (blocking) release
# # (nonblocking) attempt
# # (nonblocking) grab it
# # (nonblocking) release
# # (blocking) grab it
# # (nonblocking) attempt
# # (blocking) release
# # (nonblocking) attempt
# # (nonblocking) grab it
# # (nonblocking) release
# # (blocking) grab it
# # (blocking) release
# # (nonblocking) attempt
# # (nonblocking) grab it
# # (nonblocking) release
# # (nonblocking) attempt : 5, grab : 3



'파이썬(PYTHON)' 카테고리의 다른 글

파이썬의 스레드(thread)4  (0) 2020.08.27
파이썬의 스레드(thread)3  (0) 2020.08.27
파이썬의 스레드(thread)1  (0) 2020.08.24
파이썬의 기본 문법3  (0) 2020.08.23
파이썬의 기본 문법2  (0) 2020.08.23

"프로그래밍 언어의 개념과 흐름에 대한 고찰 - 파이썬답게 코딩하기" 학습중...


동시성과 관련한 thread 기법에 대해 어렴풋이 알거나 몰랐던 내용들 몇가지 정리해봅니다.



# import threading
# def worker(count) :
# print("name : %s, argument : %s" % (threading.currentThread().getName(), count))
# def main() :
# for i in range(10) :
# t = threading.Thread(target = worker, name = "thread %i" %i, args = (i,))
# t.start()
# if __name__ == "__main__" :
# main()
#
# name : thread 0, argument : 0
# name : thread 1, argument : 1
# name : thread 2, argument : 2
# name : thread 3, argument : 3
# name : thread 4, argument : 4
## 책에서는 실행할 때마다 실행 순서가 달라지지만 실제 코딩해보니 실행순서는 순서대로 진행됨. 결국 코어가 1개면 스레드를 실행하
## 더라도 순차적으로 실행되지만 CPU가 여러개이면 비순차적으로 실행될 수 있다.




# import threading
#
# class Worker(threading.Thread) :
# def __init__(self, args, name = ""):
# threading.Thread.__init__(self)
# self.args = args
# def run(self):
# print("name : %s, argument : %s" % (threading.currentThread().getName(), self.args[0]))
#
# def main() :
# for i in range(5) :
# t = Worker(name = "thread %i" %i, args = (i,))
# t.start()
#
# if __name__ == "__main__" :
# main()
# name : Thread-1, argument : 0
# name : Thread-2, argument : 1
# name : Thread-3, argument : 2
# name : Thread-4, argument : 3
# name : Thread-5, argument : 4
## 클래스로도 스레드를 구현할 수 있다.




# import threading
# import logging
#
# logging.basicConfig(level = logging.DEBUG, format = "name : %(threadName)s, argument : %(message)s")
#
# def worker(count) :
# logging.debug(count)
#
# def main() :
# for i in range(5) :
# t = threading.Thread(target = worker, name = "thread %i" %i, args = (i,))
# t.start()
#
# if __name__ == "__main__" :
# main()
# name : thread 0, argument : 0
# name : thread 1, argument : 1
# name : thread 2, argument : 2
# name : thread 3, argument : 3
# name : thread 4, argument : 4
## 로깅 함수로 print 동작을 대체함. python2에서는 thread 구현시 print로 출력시 불필요한 공백이 함께 출력되는 등 구현상의 문제가
## 있어서 logging 사용이 필요했음.




# import time
# import threading
# import logging
#
# logging.basicConfig(level = logging.DEBUG, format = "(%(threadName)s) %(message)s")
#
# def demon() :
# logging.debug("start")
# time.sleep(5)
# logging.debug("exit")
#
# def main() :
# t = threading.Thread(name = "demon", target = demon)
# t.setDaemon(True)
# t.start()
#
# if __name__ =="__main__" :
# main()
# (demon) start
## daemon실행의 이점은 프로그램 종료시 스레도도 같이 종료되도록 함. 그렇지 않을 경우 메인 프로그램 종료시 스레드의 종료를 기다림.
## start만 실행하고 메인 프로그램 종료시 같이 종료되어 exit가 출력되지 않음




# import time
# import threading
# import logging
#
# logging.basicConfig(level = logging.DEBUG, format = "(%(threadName)s) %(message)s")
#
# def demon() :
# logging.debug("start")
# time.sleep(5)
# logging.debug("exit")
#
# def main() :
# t = threading.Thread(name = "demon", target = demon)
# t.setDaemon(True)
# t.start()
# t.join()
#
# if __name__ =="__main__" :
# main()
#
# (demon) start
# (demon) exit
## t.join()을 추가함으로써 exit출력됨. 곧 데몬 스레드 종료될 때까지 기다리는 동작을 함.



'파이썬(PYTHON)' 카테고리의 다른 글

파이썬의 스레드(thread)3  (0) 2020.08.27
파이썬의 스레드(thread)2  (0) 2020.08.25
파이썬의 기본 문법3  (0) 2020.08.23
파이썬의 기본 문법2  (0) 2020.08.23
통계 - 주택 청약 통장 계좌수  (0) 2020.08.22

"프로그래밍 언어의 개념과 흐름에 대한 고찰 - 파이썬답게 코딩하기" 학습중...


기본 문법과 관련하여 어렴풋이 알거나 몰랐던 내용들 몇가지 정리해봅니다.



#!/usr/bin/python3
# import time
# from functools import update_wrapper
#
# class MeasureRuntime :
# def __init__(self, f):
# self.func = f
# update_wrapper(self, self.func)
# def __call__(self, *args, **kwargs):
# start = time.time()
# result = self.func(*args, **kwargs)
# end = time.time()
# print("'%s' function running time : %s" %(self.func.__name__, end - start))
# return result
#
# @MeasureRuntime
# def worker(delay_time) :
# time.sleep(delay_time)
#
# if __name__ == "__main__" :
# worker(5)

# 'worker' function running time : 5.000048398971558
## __call__ 메서드가 클로저로 되어 있지 않다. 함수를 데코레이터로 한 경우 클로저로 구현했으나 클래스를 데코레이터로 한 예제
## 에서는 클로저를 사용하지 않았다.



# import time
# from functools import update_wrapper
#
# class MeasureRuntime :
# def __init__(self, f):
# self.func = f
# update_wrapper(self, self.func)
# def __call__(self, *args, **kwargs):
# start = time.time()
# result = self.func(*args, **kwargs)
# end = time.time()
# print("'%s' function running time : %s" %(self.func.__name__, end - start))
# return result
#
# def worker(delay_time) :
# time.sleep(delay_time)
#
# if __name__ == "__main__" :
# f = MeasureRuntime(worker)
# f(5)
#
# 'worker' function running time : 5.003544092178345
## 데코레이터를 사용한 것과 동일한 결과.
## __init__는 생성자로 사용. 즉 클래스를 사용하기 위해서 정의할 때 호출
## __call__은 클래스를 함수처럼 사용할 때 호출. 즉 클래스 이름으로 instance를 만들어 사용 가능. 원래같으면 f.example()로 표현
## 하지만 __call__을 선언함으로써 class 이름만으로도 함수처럼 동작한다.




# import time
# from functools import wraps
#
# class MeasureRuntime :
# def __init__(self, active_state):
# self.measure_active = active_state
# def __call__(self, func):
# @wraps(func)
# def wrapper(*args, **kwargs) :
# if self.measure_active is False :
# return func(*args, **kwargs)
# start = time.time()
# result = func(*args, **kwargs)
# end = time.time()
# print("'%s' function running time : %s" % (func.__name__, end - start))
# return result
# return wrapper
#
# @MeasureRuntime(True)
# def active_worker(delay_time):
# time.sleep(delay_time)
#
# @MeasureRuntime(False)
# def non_active_worker(delay_time):
# time.sleep(5)
#
# if __name__ == "__main__" :
# active_worker(5)
# non_active_worker(5)

# 'active_worker' function running time : 5.012182235717773

## 데코레이터에 매개변수가 있는 경우에는 클로저의 형태를 구현해야 한다.




# def main() :
# x = {1, 2, 3}
# y = {"red" : 1, "blue" : 2, "green" : 3}
#
# x_iterator = iter(x)
# y_iterator = iter(y)
# print("=== print type ===")
# print("list type : %s" % type(x))
# print("dictionary type : %s" % type(y))
# print("list iterator type : %s" % type(x_iterator))
# print("dictionary iterator type : %s" % type(y_iterator))
#
# print("=== print next ===")
# print("list iterator next : %s" % next(x_iterator))
# print("dictionary iterator next : %s" % next(y_iterator))
# print("list next : %s" % next(x))
# print("dictionary next : %s" % next(y))
#
# if __name__ == "__main__" :
# main()

# === print type ===
# list type : <class 'set'>
# dictionary type : <class 'dict'>
# list iterator type : <class 'set_iterator'>
# dictionary iterator type : <class 'dict_keyiterator'>
# === print next ===
# list iterator next : 1
# dictionary iterator next : red
# Traceback (most recent call last):
# File "C:/PythonProject/autobuy/test4.py", line 109, in <module>
# main()
# File "C:/PythonProject/autobuy/test4.py", line 105, in main
# print("list next : %s" % next(x))
# TypeError: 'set' object is not an iterator

## iterable iterator의 차이에서 오는 오류. iterable은 가지고 있는 값을 한번에 반환하거나 하나씩 반환할 수 있는 개체
## iterale 개체는 next 함수 사용시 오류 발생, list iterator가 아니라는 것. iterator는 가지고 있는 값을 한 번에 하나씩만
## 반환하는 개체. for문은 자동적으로 iterable 개체늘 iterator로 변화하는 함수가 내장됨.
## iterator는 한번에 하나씩만 반환하는 개체이며 파이썬의 내장 함수인 next를 통해서 값을 순차적으로 반환, 상태 저장 및 순차 출력
## 범위를 넘는 iterator 실행시 StopIteration 예외를 발생시키며 for문에는 이러한 예외 처리가 내장됨.




## 제네레이터(Generator) - 루프의 반복 동작을 제어하는 특수한 함수. 혹은 이터레이터를 반환하고 yield 구문을 포함하는 함수

# def gen() :
# value = 1
# while True :
# value = yield value
#
# def main() :
# print("=== print gen function ===")
# g = gen()
# print(next(g))
# print(g.send(2))
# print(g.send(10))
# print(g.send(5))
# print(next(g))
#
# if __name__ == "__main__" :
# main()

# === print gen function ===
# 1
# 2
# 10
# 5
# None
## 제네레이터를 응용하면 함수들 간의 호출 흐름을 제어할 수 있고 데이터도 전달할 수 있다.




# v_list = [1, 2, 3]
# v_dict_key = ['korea', 'japan', 'china']
# v_dict_value = [82, 81, 86]
#
# def print_list_with_comprehension() :
# v_list_comprehension = [x*x for x in v_list]
# print(v_list_comprehension)
#
# def print_list_with_for() :
# result = []
# for v in v_list :
# result.append(v*v)
# print(result)
#
# def print_dict_with_comprehension() :
# v_dict_comprehension = {k:v for k, v in zip(v_dict_key, v_dict_value)}
# print(v_dict_comprehension)
#
# def print_dict_with_for() :
# result = {}
# for k, v in zip(v_dict_key, v_dict_value) :
# result[k] = v
# print(result)
#
# def main() :
# print("=== print list ===")
# print(v_list)
# print_list_with_comprehension()
# print_list_with_for()
#
# print("=== print dict ===")
# print(v_dict_key)
# print(v_dict_value)
# print_dict_with_comprehension()
# print_dict_with_for()
#
# if __name__ == "__main__" :
# main()

# === print list ===
# [1, 2, 3]
# [1, 4, 9]
# [1, 4, 9]
# === print dict ===
# ['korea', 'japan', 'china']
# [82, 81, 86]
# {'korea': 82, 'japan': 81, 'china': 86}
# {'korea': 82, 'japan': 81, 'china': 86}

## comprehension [] {}를 사용하지만 generator ()를 사용한다.




## equality vs identity 즉 동등성을 검증할 때는 ==, != 사용하고 동일성을 검증할 때는 is, is not을 사용 Boolean True/False
## 비교할 때 if문에 변수만 사용한다. if x : Why ? 가독성과 효율성 재고.

# import timeit
#
# def average(items) :
# sum = 0
# for item in items :
# sum += float(item)
# return sum / len(items)
#
# def check_performance(compare_expression, condition) :
# results = timeit.Timer(compare_expression, setup = condition).repeat(100, 10000)
# return average(results)
#
# def main() :
# print("=== compare x is not None ===")
# print("identity : %s" % check_performance("x is None", "x = 1"))
# print("equality : %s" % check_performance("x == None", "x = 1"))
#
# print("=== compare x is None ===")
# print("identity : %s" % check_performance("x is None", "x = None"))
# print("equality : %s" % check_performance("x == None", "x = None"))
#
# if __name__ == "__main__" :
# main()

# === compare x is not None ===
# identity : 0.00032601
# equality : 0.00042575800000000036
# === compare x is None ===
# identity : 0.0002833070000000003
# equality : 0.0003065150000000007

## None의 경우 특수한 경우로 동등성과 동일성 모두 보장하지만 실제로는 동일성을 보장하기 때문에 is를 사용하는 구문이 더 빠름.



'파이썬(PYTHON)' 카테고리의 다른 글

파이썬의 스레드(thread)2  (0) 2020.08.25
파이썬의 스레드(thread)1  (0) 2020.08.24
파이썬의 기본 문법2  (0) 2020.08.23
통계 - 주택 청약 통장 계좌수  (0) 2020.08.22
파이썬의 기본 문법1  (0) 2020.08.21

+ Recent posts