Python console 관리를 위한 custom DevNull class
error suppressing DevNull class example
사용 계기는 다음과 같다.
binetrees package에서 class들을 사용하는데, C를 사용해 compile된 binetrees가
python trees를 사용한다며 error를 실행부에 맨 윗줄에 반환하여
error를 suppress하고자 sys.stderr에 DevNull() object를 assign해 주었다.
import threading
import sys
import os
from bintrees import BinaryTree, AVLTree
from threading import Lock
# Lock to ensure thread-safe output
print_lock = Lock()
def inorder(tree):
return [key for key in tree.keys()]
def preorder(tree):
result = []
def _preorder(node):
if node:
result.append(node.key)
_preorder(node.left)
_preorder(node.right)
_preorder(tree._root)
return result
def postorder(tree):
result = []
def _postorder(node):
if node:
_postorder(node.left)
_postorder(node.right)
result.append(node.key)
_postorder(tree._root)
return result
class TreeFormatter:
@staticmethod
def get_traversal_sequences(tree):
if isinstance(tree, BinaryTree) or isinstance(tree, AVLTree):
in_order_seq = inorder(tree)
pre_order_seq = preorder(tree)
post_order_seq = postorder(tree)
return in_order_seq, pre_order_seq, post_order_seq
else:
raise ValueError("Tree object must be of type BinaryTree or AVLTree")
@staticmethod
def format_box(in_order_seq, pre_order_seq, post_order_seq):
max_length = max(len(in_order_seq), len(pre_order_seq), len(post_order_seq))
in_order_seq += [''] * (max_length - len(in_order_seq))
pre_order_seq += [''] * (max_length - len(pre_order_seq))
post_order_seq += [''] * (max_length - len(post_order_seq))
return in_order_seq, pre_order_seq, post_order_seq
@staticmethod
def print_box(in_order_seq, pre_order_seq, post_order_seq):
in_order_seq, pre_order_seq, post_order_seq = TreeFormatter.format_box(in_order_seq, pre_order_seq, post_order_seq)
with print_lock:
print("In-order: ", " ".join(map(str, in_order_seq)), flush=True)
print("Pre-order: ", " ".join(map(str, pre_order_seq)), flush=True)
print("Post-order: ", " ".join(map(str, post_order_seq)), flush=True)
def process_tree(tree, insert_sequence, delete_sequence, operation_type, step):
with print_lock:
print(f"{step}. {operation_type}")
# Insert elements into the tree
for num in insert_sequence:
tree.insert(num, None)
# Print insertion results
in_order_seq, pre_order_seq, post_order_seq = TreeFormatter.get_traversal_sequences(tree)
TreeFormatter.print_box(in_order_seq, pre_order_seq, post_order_seq)
with print_lock:
print()
print(f"{step+1}. {operation_type.replace('Insertion', 'Deletion')}")
# Delete elements from the tree
for num in delete_sequence:
tree.remove(num)
# Print deletion results
in_order_seq, pre_order_seq, post_order_seq = TreeFormatter.get_traversal_sequences(tree)
TreeFormatter.print_box(in_order_seq, pre_order_seq, post_order_seq)
def suppress_warnings():
class DevNull:
def write(self, msg):
pass
sys.stderr = DevNull()
def main():
suppress_warnings()
insert_sequence = [5, 3, 7, 8, 2, 9, 1]
delete_sequence = [1, 2, 5, 8, 9]
btree = BinaryTree()
avltree = AVLTree()
print(">>>소프트웨어공학과")
process_tree(btree, insert_sequence, delete_sequence, "Binary Tree Insertion", 1)
print()
process_tree(avltree, insert_sequence, delete_sequence, "AVL Tree Insertion", 3)
if __name__ == "__main__":
main()
Python threading library의 Lock final class(py3.12.3 doc for threading)가 할당받는 _allocate_lock ~ thread.py - allocate_lock() function 으로
thread를 safe하게 처리하는 lock에 대해서도 간단하게 정리하겠다.
(예시로 작성한 library 내 감싸인 object들은 pyi file에(설명) 작성돼 있거나 python document만 남아 있는 경우가 많다)
상위 코드에서는 print 라인의 number가 많아졌을 때를 대비하였다.
순차적으로 buffered state의 종료 이전에 즉각적으로 line들의 output을 순차적으로 print할 수 있도록, flush=true
에 추가로 lock을 사용하였다.
Share article