├── 8th_members ├── .gitkeep ├── 고동희 │ ├── 6주차.md │ ├── 12주차.md │ ├── 8주차.md │ ├── 7주차.md │ ├── week_1.png │ ├── week_2.png │ ├── week_6.png │ ├── week_7.png │ ├── week_8.png │ ├── week_12.png │ ├── week_3_1.png │ ├── week_3_2.png │ ├── week_3_3.png │ ├── week_4_1.png │ ├── week_4_2.png │ ├── 2주차.md │ ├── week_10_single.png │ ├── week_13_debug.png │ ├── week_9_multi.png │ ├── week_9_single.png │ ├── week_13_profile.png │ ├── week_10_multi_threading.png │ ├── week_10_multi_threading2.png │ ├── 13주차.md │ ├── main.py │ ├── 4주차.md │ ├── 9주차.md │ ├── 1주차.md │ ├── 10주차.md │ ├── 3주차.md │ └── 11주차.md ├── 김원경 │ ├── image.png │ ├── 5주차.md │ ├── 8주차.md │ ├── 4주차.md │ ├── 3주차.md │ ├── 2주차.md │ ├── 9주차.md │ ├── 7주차.md │ ├── 1주차.md │ ├── 13주차.md │ ├── 10주차.md │ ├── 6주차.md │ ├── 11주차.md │ └── 12주차.md ├── 이성범 │ ├── 5주차.md │ ├── 6주차.md │ ├── image │ │ ├── 10_week.png │ │ ├── 12_week.png │ │ ├── 1_week.png │ │ ├── 4_week_2.png │ │ ├── 5_week.png │ │ ├── 6_week.png │ │ ├── 7_week.png │ │ ├── 8_week.png │ │ ├── 9_week.png │ │ ├── 4_week_1-1.png │ │ ├── 4_week_1-2.png │ │ ├── 2_week_build.png │ │ ├── 2_week_pass.png │ │ ├── 3_week_find_spec.png │ │ ├── 3_week_interpreter.png │ │ └── 3_week_runtime_flag.png │ ├── 7주차.md │ ├── 8주차.md │ ├── 2주차.md │ ├── 1주차.md │ ├── 4주차.md │ ├── 3주차.md │ ├── 9주차.md │ ├── 10주차.md │ ├── 12주차.md │ └── 11주차.md ├── 김서현 │ ├── mission1.png │ └── 1주차.md ├── 이용준 │ ├── 5주차.md │ ├── 7주차.md │ ├── 6주차.md │ ├── 8주차.md │ ├── 9주차.md │ ├── 4주차.md │ ├── 2주차.md │ ├── 3주차.md │ └── 1주차.md ├── 하상천 │ ├── 5주차.md │ ├── 8주차.md │ ├── 6주차.md │ ├── 2주차.md │ ├── 7주차.md │ ├── 1주차.md │ ├── 4주차.md │ ├── 3주차.md │ ├── 12주차.md │ ├── 9주차.md │ ├── 10주차.md │ └── 11주차.md ├── 전희선 │ ├── 5주차.md │ ├── 1주차.md │ ├── 2주차.md │ ├── 8주차.md │ ├── 6주차.md │ ├── 7주차.md │ ├── 4주차.md │ ├── 9주차.md │ ├── 10주차.md │ ├── 3주차.md │ ├── 12주차.md │ └── 13주차.md ├── 김필모 │ ├── 5주차.md │ ├── 8주차.md │ ├── 1주차.md │ ├── 3주차.md │ ├── 2주차.md │ ├── 13주차.md │ ├── 9주차.md │ ├── 4주차.md │ ├── 12주차.md │ ├── 7주차.md │ ├── 6주차.md │ ├── 11주차.md │ └── 10주차.md ├── 김진아 │ ├── 5주차.md │ ├── 10주차.md │ ├── 8주차.md │ ├── 9주차.md │ ├── 2주차.md │ ├── 1주차.md │ ├── 4주차.md │ ├── 3주차.md │ ├── 7주차.md │ ├── 6주차.md │ ├── 13주차.md │ └── 12주차.md └── 이용우 │ ├── 5주차.md │ ├── 13주차.md │ ├── 7주차.md │ ├── 10주차.md │ ├── 6주차.md │ ├── 4주차.md │ ├── 1주차.md │ ├── 9주차.md │ ├── 2주차.md │ ├── 12주차.md │ └── 3주차.md ├── book ├── docs │ ├── 9_1_memory_pool.md │ ├── 0_1_directory_structure.md │ ├── sample │ │ └── markdown-example.md │ ├── 10_0_parallel_and_concurrent.md │ ├── 0_0_dev_env_setup.md │ ├── 2_0_settings.md │ ├── 1_0_welcome_to_cpython.md │ ├── 12_0_standard_library.md │ ├── 9_0_memory.md │ ├── 14_0_c_extension.md │ ├── 13_0_test_suite.md │ ├── 3_0_compile.md │ └── 10_2_thread.md ├── PseudoLab_logo.png ├── images │ ├── 3_compile │ │ └── 00_pgo.png │ ├── 4_grammar │ │ ├── tokens.png │ │ ├── small_stmt.png │ │ ├── code_tokenized.png │ │ ├── 03_train_diagram_try.png │ │ ├── 01_train_diagram_coffee.png │ │ ├── 02_train_diagram_while.jpeg │ │ └── 00_train_diagram.svg │ ├── 9_memory │ │ ├── 03_arena.jpg │ │ ├── 04_pool.png │ │ ├── 01_C_memory_allocation.png │ │ └── 02_cpython_memory_hierarchy.png │ ├── 10_2_thread │ │ ├── untitled.png │ │ ├── untitled_1.png │ │ ├── untitled_2.png │ │ ├── untitled_3.png │ │ ├── untitled_4.png │ │ ├── untitled_5.png │ │ ├── untitled_6.png │ │ ├── untitled_7.png │ │ ├── untitled_8.png │ │ └── untitled_9.png │ ├── 6_rexing │ │ ├── 00_CST_EXPR.jpg │ │ ├── 01_parse_tree.png │ │ ├── 03_Parsing_Name.jpg │ │ ├── 02_Parser_Tokenizer.jpg │ │ ├── 05_Grammar_Grammar.png │ │ ├── 08.Node_Properties.png │ │ ├── 09.Pow_Example_AST.png │ │ ├── 04_Input_to_Compiler.png │ │ ├── 07.AST_Visualization.png │ │ ├── 06_Code_Objects_Properties.png │ │ └── 10.Pow_Example_Node_Properties.png │ ├── 8_eval_loop │ │ ├── 01_eval1.JPG │ │ ├── 02_eval2.JPG │ │ ├── 03_eval3.JPG │ │ ├── 04_eval4.JPG │ │ ├── 05_eval5.JPG │ │ ├── 06_eval6.JPG │ │ └── 07_eval7.JPG │ ├── 5_config_and_input │ │ ├── config.png │ │ ├── input.png │ │ ├── mermaid.png │ │ └── interpreter_overview.png │ ├── 2_settings │ │ ├── 00_vscode_plugin.png │ │ ├── 02_cpython_debugging.png │ │ └── 01_tasks_explorer_result.png │ ├── 7_compiler │ │ ├── 02_compile_status.png │ │ ├── 00_compile_process.png │ │ ├── 01_compile_process2.png │ │ ├── 03_compile_instaviz.png │ │ └── 04_compile_instaviz2.png │ ├── 10_parallel_and_concurrent │ │ ├── mp1.png │ │ ├── mp2.png │ │ ├── _main.png │ │ ├── pickle.png │ │ ├── pip2.png │ │ ├── pipe.png │ │ ├── pipe2.png │ │ ├── pipe3.png │ │ ├── queue1.png │ │ ├── queue2.png │ │ ├── queue3.png │ │ ├── queue4.png │ │ ├── parallel.png │ │ ├── process.png │ │ ├── concurrency.png │ │ └── process_thread.png │ ├── 13_test_suite │ │ └── 00_test_harness.png │ ├── 14_c_extension │ │ ├── 00_vscode_setting.png │ │ └── 01_vscode_setting.png │ └── 12_standard_library │ │ └── 00_library_directory.png ├── c_extension_sample │ ├── setup.py │ └── fputsmodule.c ├── intro.md ├── _toc.yml └── _config.yml ├── requirements.txt ├── .github └── workflows │ └── main.yml ├── README.md └── .gitignore /8th_members/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /book/docs/9_1_memory_pool.md: -------------------------------------------------------------------------------- 1 | # 메모리 풀 -------------------------------------------------------------------------------- /8th_members/고동희/6주차.md: -------------------------------------------------------------------------------- 1 | # 6주차 2 | 3 | ## 프레임 객체 생성하기 4 | ![alt text](week_6.png) -------------------------------------------------------------------------------- /8th_members/고동희/12주차.md: -------------------------------------------------------------------------------- 1 | # 12주차 2 | 3 | ## unittest 사용하기 4 | ![alt text](week_12.png) -------------------------------------------------------------------------------- /8th_members/고동희/8주차.md: -------------------------------------------------------------------------------- 1 | # 8주차 2 | 3 | ## sys.getrefcount 사용해보기 4 | ![alt text](week_8.png) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/requirements.txt -------------------------------------------------------------------------------- /8th_members/고동희/7주차.md: -------------------------------------------------------------------------------- 1 | # 7주차 2 | 3 | ## tracemalloc 모듈 사용해서 직접 메모리 확인해보기 4 | ![alt text](week_7.png) -------------------------------------------------------------------------------- /book/PseudoLab_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/PseudoLab_logo.png -------------------------------------------------------------------------------- /8th_members/고동희/week_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_1.png -------------------------------------------------------------------------------- /8th_members/고동희/week_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_2.png -------------------------------------------------------------------------------- /8th_members/고동희/week_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_6.png -------------------------------------------------------------------------------- /8th_members/고동희/week_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_7.png -------------------------------------------------------------------------------- /8th_members/고동희/week_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_8.png -------------------------------------------------------------------------------- /8th_members/김원경/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/김원경/image.png -------------------------------------------------------------------------------- /8th_members/이성범/5주차.md: -------------------------------------------------------------------------------- 1 | # 5주차 2 | 3 | ## ‘거의 같음’ 연산자 구현 4 |

-------------------------------------------------------------------------------- /8th_members/고동희/week_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_12.png -------------------------------------------------------------------------------- /8th_members/고동희/week_3_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_3_1.png -------------------------------------------------------------------------------- /8th_members/고동희/week_3_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_3_2.png -------------------------------------------------------------------------------- /8th_members/고동희/week_3_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_3_3.png -------------------------------------------------------------------------------- /8th_members/고동희/week_4_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_4_1.png -------------------------------------------------------------------------------- /8th_members/고동희/week_4_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_4_2.png -------------------------------------------------------------------------------- /8th_members/김서현/mission1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/김서현/mission1.png -------------------------------------------------------------------------------- /8th_members/이성범/6주차.md: -------------------------------------------------------------------------------- 1 | # 6주차 2 | 3 | ## 파이썬에서 프레임 객체 접근해보기 4 |

-------------------------------------------------------------------------------- /8th_members/고동희/2주차.md: -------------------------------------------------------------------------------- 1 | # 2주차 2 | 3 | ## 문법 다시 생성하기 4 | `break` 대신 `bye`도 사용할 수 있도록 문법을 변경함. 5 | -------------------------------------------------------------------------------- /8th_members/고동희/week_10_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_10_single.png -------------------------------------------------------------------------------- /8th_members/고동희/week_13_debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_13_debug.png -------------------------------------------------------------------------------- /8th_members/고동희/week_9_multi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_9_multi.png -------------------------------------------------------------------------------- /8th_members/고동희/week_9_single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_9_single.png -------------------------------------------------------------------------------- /8th_members/이성범/image/10_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/10_week.png -------------------------------------------------------------------------------- /8th_members/이성범/image/12_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/12_week.png -------------------------------------------------------------------------------- /8th_members/이성범/image/1_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/1_week.png -------------------------------------------------------------------------------- /8th_members/이성범/image/4_week_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/4_week_2.png -------------------------------------------------------------------------------- /8th_members/이성범/image/5_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/5_week.png -------------------------------------------------------------------------------- /8th_members/이성범/image/6_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/6_week.png -------------------------------------------------------------------------------- /8th_members/이성범/image/7_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/7_week.png -------------------------------------------------------------------------------- /8th_members/이성범/image/8_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/8_week.png -------------------------------------------------------------------------------- /8th_members/이성범/image/9_week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/9_week.png -------------------------------------------------------------------------------- /book/images/3_compile/00_pgo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/3_compile/00_pgo.png -------------------------------------------------------------------------------- /book/images/4_grammar/tokens.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/4_grammar/tokens.png -------------------------------------------------------------------------------- /book/images/9_memory/03_arena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/9_memory/03_arena.jpg -------------------------------------------------------------------------------- /book/images/9_memory/04_pool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/9_memory/04_pool.png -------------------------------------------------------------------------------- /8th_members/고동희/week_13_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_13_profile.png -------------------------------------------------------------------------------- /8th_members/이성범/7주차.md: -------------------------------------------------------------------------------- 1 | # 7주차 2 | 3 | ## tracemalloc 모듈 사용해서 직접 메모리 확인해보기 4 |

-------------------------------------------------------------------------------- /8th_members/이성범/image/4_week_1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/4_week_1-1.png -------------------------------------------------------------------------------- /8th_members/이성범/image/4_week_1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/4_week_1-2.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled.png -------------------------------------------------------------------------------- /book/images/4_grammar/small_stmt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/4_grammar/small_stmt.png -------------------------------------------------------------------------------- /book/images/6_rexing/00_CST_EXPR.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/00_CST_EXPR.jpg -------------------------------------------------------------------------------- /book/images/8_eval_loop/01_eval1.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/8_eval_loop/01_eval1.JPG -------------------------------------------------------------------------------- /book/images/8_eval_loop/02_eval2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/8_eval_loop/02_eval2.JPG -------------------------------------------------------------------------------- /book/images/8_eval_loop/03_eval3.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/8_eval_loop/03_eval3.JPG -------------------------------------------------------------------------------- /book/images/8_eval_loop/04_eval4.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/8_eval_loop/04_eval4.JPG -------------------------------------------------------------------------------- /book/images/8_eval_loop/05_eval5.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/8_eval_loop/05_eval5.JPG -------------------------------------------------------------------------------- /book/images/8_eval_loop/06_eval6.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/8_eval_loop/06_eval6.JPG -------------------------------------------------------------------------------- /book/images/8_eval_loop/07_eval7.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/8_eval_loop/07_eval7.JPG -------------------------------------------------------------------------------- /8th_members/이성범/image/2_week_build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/2_week_build.png -------------------------------------------------------------------------------- /8th_members/이성범/image/2_week_pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/2_week_pass.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_1.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_2.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_3.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_4.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_5.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_6.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_7.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_8.png -------------------------------------------------------------------------------- /book/images/10_2_thread/untitled_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_2_thread/untitled_9.png -------------------------------------------------------------------------------- /book/images/6_rexing/01_parse_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/01_parse_tree.png -------------------------------------------------------------------------------- /8th_members/이성범/8주차.md: -------------------------------------------------------------------------------- 1 | # 8주차 2 | 3 | ## 원하는 라이브러리 import 해보고, 참조 카운트가 어떻게 바뀌는지 출력해보기 4 |

-------------------------------------------------------------------------------- /book/images/4_grammar/code_tokenized.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/4_grammar/code_tokenized.png -------------------------------------------------------------------------------- /book/images/5_config_and_input/config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/5_config_and_input/config.png -------------------------------------------------------------------------------- /book/images/5_config_and_input/input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/5_config_and_input/input.png -------------------------------------------------------------------------------- /book/images/6_rexing/03_Parsing_Name.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/03_Parsing_Name.jpg -------------------------------------------------------------------------------- /8th_members/고동희/week_10_multi_threading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_10_multi_threading.png -------------------------------------------------------------------------------- /8th_members/고동희/week_10_multi_threading2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/고동희/week_10_multi_threading2.png -------------------------------------------------------------------------------- /8th_members/이성범/image/3_week_find_spec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/3_week_find_spec.png -------------------------------------------------------------------------------- /8th_members/이성범/image/3_week_interpreter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/3_week_interpreter.png -------------------------------------------------------------------------------- /book/images/2_settings/00_vscode_plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/2_settings/00_vscode_plugin.png -------------------------------------------------------------------------------- /book/images/5_config_and_input/mermaid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/5_config_and_input/mermaid.png -------------------------------------------------------------------------------- /book/images/6_rexing/02_Parser_Tokenizer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/02_Parser_Tokenizer.jpg -------------------------------------------------------------------------------- /book/images/6_rexing/05_Grammar_Grammar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/05_Grammar_Grammar.png -------------------------------------------------------------------------------- /book/images/6_rexing/08.Node_Properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/08.Node_Properties.png -------------------------------------------------------------------------------- /book/images/6_rexing/09.Pow_Example_AST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/09.Pow_Example_AST.png -------------------------------------------------------------------------------- /book/images/7_compiler/02_compile_status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/7_compiler/02_compile_status.png -------------------------------------------------------------------------------- /8th_members/고동희/13주차.md: -------------------------------------------------------------------------------- 1 | # 13주차 2 | 3 | ## pdb 실행해보기 4 | ![alt text](week_13_debug.png) 5 | 6 | ## CProfile 실행해보기 7 | ![alt text](week_13_profile.png) -------------------------------------------------------------------------------- /8th_members/이성범/image/3_week_runtime_flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/8th_members/이성범/image/3_week_runtime_flag.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/mp1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/mp1.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/mp2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/mp2.png -------------------------------------------------------------------------------- /book/images/13_test_suite/00_test_harness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/13_test_suite/00_test_harness.png -------------------------------------------------------------------------------- /book/images/4_grammar/03_train_diagram_try.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/4_grammar/03_train_diagram_try.png -------------------------------------------------------------------------------- /book/images/6_rexing/04_Input_to_Compiler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/04_Input_to_Compiler.png -------------------------------------------------------------------------------- /book/images/6_rexing/07.AST_Visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/07.AST_Visualization.png -------------------------------------------------------------------------------- /book/images/7_compiler/00_compile_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/7_compiler/00_compile_process.png -------------------------------------------------------------------------------- /book/images/7_compiler/01_compile_process2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/7_compiler/01_compile_process2.png -------------------------------------------------------------------------------- /book/images/7_compiler/03_compile_instaviz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/7_compiler/03_compile_instaviz.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/_main.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/pickle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/pickle.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/pip2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/pip2.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/pipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/pipe.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/pipe2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/pipe2.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/pipe3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/pipe3.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/queue1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/queue1.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/queue2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/queue2.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/queue3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/queue3.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/queue4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/queue4.png -------------------------------------------------------------------------------- /book/images/14_c_extension/00_vscode_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/14_c_extension/00_vscode_setting.png -------------------------------------------------------------------------------- /book/images/14_c_extension/01_vscode_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/14_c_extension/01_vscode_setting.png -------------------------------------------------------------------------------- /book/images/2_settings/02_cpython_debugging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/2_settings/02_cpython_debugging.png -------------------------------------------------------------------------------- /book/images/4_grammar/01_train_diagram_coffee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/4_grammar/01_train_diagram_coffee.png -------------------------------------------------------------------------------- /book/images/4_grammar/02_train_diagram_while.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/4_grammar/02_train_diagram_while.jpeg -------------------------------------------------------------------------------- /book/images/7_compiler/04_compile_instaviz2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/7_compiler/04_compile_instaviz2.png -------------------------------------------------------------------------------- /book/images/9_memory/01_C_memory_allocation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/9_memory/01_C_memory_allocation.png -------------------------------------------------------------------------------- /8th_members/이용준/5주차.md: -------------------------------------------------------------------------------- 1 | # 거의 같음 연산자 구현 2 | 3 | ![mission-5](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/45a07011-107c-46cd-a35f-43581ae91872) 4 | -------------------------------------------------------------------------------- /8th_members/하상천/5주차.md: -------------------------------------------------------------------------------- 1 | # ‘거의 같음’ 연산자 구현하기 2 | 3 | ![image](https://github.com/Pseudo-Lab/CPython-Guide/assets/54731898/08dc365c-1cd5-401b-b753-769b7a52c1a5) 4 | -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/parallel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/parallel.png -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/process.png -------------------------------------------------------------------------------- /book/images/2_settings/01_tasks_explorer_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/2_settings/01_tasks_explorer_result.png -------------------------------------------------------------------------------- /book/images/6_rexing/06_Code_Objects_Properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/06_Code_Objects_Properties.png -------------------------------------------------------------------------------- /8th_members/고동희/main.py: -------------------------------------------------------------------------------- 1 | import instaviz 2 | 3 | def hello(): 4 | name = 'donghee' 5 | text = 'hello ' + name 6 | return name 7 | 8 | instaviz.show(hello) -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/concurrency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/concurrency.png -------------------------------------------------------------------------------- /book/images/9_memory/02_cpython_memory_hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/9_memory/02_cpython_memory_hierarchy.png -------------------------------------------------------------------------------- /book/images/12_standard_library/00_library_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/12_standard_library/00_library_directory.png -------------------------------------------------------------------------------- /book/images/5_config_and_input/interpreter_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/5_config_and_input/interpreter_overview.png -------------------------------------------------------------------------------- /book/images/6_rexing/10.Pow_Example_Node_Properties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/6_rexing/10.Pow_Example_Node_Properties.png -------------------------------------------------------------------------------- /8th_members/고동희/4주차.md: -------------------------------------------------------------------------------- 1 | # 4주차 2 | 3 | ## instaviz로 AST 시각화 해보기 4 | 5 | 6 | ## ‘거의 같음’ 연산자를 문법에 추가하고 AlE타입의 객체를 출력 해보기 7 | -------------------------------------------------------------------------------- /8th_members/김원경/5주차.md: -------------------------------------------------------------------------------- 1 | # ‘거의 같음’ 연산자 구현하기 2 | image -------------------------------------------------------------------------------- /8th_members/하상천/8주차.md: -------------------------------------------------------------------------------- 1 | ## 8주차 미션 2 | 3 | image 4 | -------------------------------------------------------------------------------- /book/images/10_parallel_and_concurrent/process_thread.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pseudo-Lab/CPython-Guide/HEAD/book/images/10_parallel_and_concurrent/process_thread.png -------------------------------------------------------------------------------- /8th_members/이용준/7주차.md: -------------------------------------------------------------------------------- 1 | ## tracemalloc 모듈 사용해서 직접 메모리 확인해보기 2 | 3 | ![mission-7](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/7ccf92ee-d036-44a2-892b-61dcbccc3ee4) 4 | -------------------------------------------------------------------------------- /8th_members/전희선/5주차.md: -------------------------------------------------------------------------------- 1 | - ‘거의 같음’ 연산자 구현 2 |
image 3 | -------------------------------------------------------------------------------- /8th_members/이용준/6주차.md: -------------------------------------------------------------------------------- 1 | # 함수를 자유롭게 2개 이상 만들어서 프레임 객체의 생성을 눈으로 확인 2 | 3 | ![mission-6](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/0138687c-747f-4340-8796-df5d03ab30b5) 4 | -------------------------------------------------------------------------------- /8th_members/고동희/9주차.md: -------------------------------------------------------------------------------- 1 | # 9주차 2 | 3 | ## 싱글 프로세스 4 | ![alt text](week_9_single.png) 5 | 6 | ## 멀티 프로세스 7 | ![alt text](week_9_multi.png) 8 | 9 | ## 결론 10 | - 싱글: 1초 11 | - 멀티: 0.48초 -------------------------------------------------------------------------------- /8th_members/이용준/8주차.md: -------------------------------------------------------------------------------- 1 | # 원하는 라이브러리 import 해보고, 참조 카운트가 어떻게 바뀌는지 출력해보기 2 | 3 | ![mission-8](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/6e1351a6-70ac-40c1-a5ac-1f272a032835) 4 | -------------------------------------------------------------------------------- /8th_members/하상천/6주차.md: -------------------------------------------------------------------------------- 1 | # 파이썬에서 프레임 객체 접근해보기 2 | 3 | image 4 | -------------------------------------------------------------------------------- /8th_members/김서현/1주차.md: -------------------------------------------------------------------------------- 1 | ### CPython 소스코드 다운로드 및 환경 구성 (화면 캡쳐) 2 | 3 | 4 | 5 | ### 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 등 6 | 7 | - 잠시 놓았던 개발과 다시 친해지고 싶어요... 8 | - 화이팅! 9 | -------------------------------------------------------------------------------- /8th_members/하상천/2주차.md: -------------------------------------------------------------------------------- 1 | - 컴파일 완료된 화면 캡쳐 2 | - 키워드 다른걸로 바꾸기 3 | 4 | image 5 | -------------------------------------------------------------------------------- /8th_members/하상천/7주차.md: -------------------------------------------------------------------------------- 1 | ## tracemalloc 모듈 사용해서 직접 메모리 확인해보기 2 | 3 | image 4 | -------------------------------------------------------------------------------- /8th_members/김필모/5주차.md: -------------------------------------------------------------------------------- 1 | # 거의 같음 연산자 구현 2 | 3 | Screenshot 2024-04-28 at 10 18 27 PM 4 | -------------------------------------------------------------------------------- /8th_members/이성범/2주차.md: -------------------------------------------------------------------------------- 1 | # 2주차 2 | 3 | ## 컴파일 4 |

5 | 6 | ## 새로운 문법 생성 7 | - pass 키워드에 LGTM을 추가 8 |

-------------------------------------------------------------------------------- /8th_members/고동희/1주차.md: -------------------------------------------------------------------------------- 1 | # 1주차 2 | 3 | ## CPython 소스코드 다운로드 및 환경 구성 4 | 5 | 6 | ## 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 7 | 1. CPython internal 뿌셔뿌셔~! 8 | 2. 운영체제, 자료구조는 덤~! 9 | 3. 열심히 하겠습니다!! 10 | -------------------------------------------------------------------------------- /8th_members/김진아/5주차.md: -------------------------------------------------------------------------------- 1 | # 4주차 2 | 3 | ## ‘거의 같음’ 연산자 구현 4 | 스크린샷 2024-04-28 오후 11 21 51 5 | -------------------------------------------------------------------------------- /8th_members/김원경/8주차.md: -------------------------------------------------------------------------------- 1 | ### 원하는 라이브러리 import 해보고, 참조 카운트가 어떻게 바뀌는지 출력해보기 2 | 스크린샷 2024-06-03 오후 5 31 27 -------------------------------------------------------------------------------- /8th_members/김진아/10주차.md: -------------------------------------------------------------------------------- 1 | # 10주차 2 | 3 | ## Port Scanner: Multi Threading 4 | 스크린샷 2024-06-09 오후 11 15 02 5 | -------------------------------------------------------------------------------- /8th_members/김필모/8주차.md: -------------------------------------------------------------------------------- 1 | # 원하는 라이브러리 import 해보고, 참조 카운트가 어떻게 바뀌는지 출력해보기 2 | 3 | Screenshot 2024-06-30 at 2 38 51 AM 4 | -------------------------------------------------------------------------------- /8th_members/김진아/8주차.md: -------------------------------------------------------------------------------- 1 | # 8주차 2 | 3 | ## 원하는 라이브러리 import 해보고, 참조 카운트가 어떻게 바뀌는지 출력해보기 4 | 스크린샷 2024-05-26 오후 11 17 08 5 | -------------------------------------------------------------------------------- /8th_members/고동희/10주차.md: -------------------------------------------------------------------------------- 1 | # 10주차 2 | 3 | ## 싱글 프로세스 + 싱글 스레드 4 | ![alt text](week_10_single.png) 5 | 6 | ## 싱글 프로세스 + 멀티 스레딩 7 | ![alt text](week_10_multi_threading.png) 8 | 9 | ## 싱글 프로세스 + 멀티 스레딩 (개수 제한) 10 | ![alt text](week_10_multi_threading2.png) -------------------------------------------------------------------------------- /8th_members/이성범/1주차.md: -------------------------------------------------------------------------------- 1 | # 1주차 2 | 3 | ## CPython 소스코드 다운로드 및 환경 구성 4 |

5 | 6 | ## 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 7 | - 이번 스터디를 통해서 Python 동작 원리를 조금 더 깊게 이해해서, 사용하고 있는 코드들의 성능을 최적화 하고 싶습니다. 8 | - CPython을 공부하려는 사람들을 위한 좋은 가이드북을 만들면 좋겠습니다. -------------------------------------------------------------------------------- /8th_members/이성범/4주차.md: -------------------------------------------------------------------------------- 1 | # 4주차 2 | 3 | ## instaviz로 AST 시각화 해보기 4 |

5 |

6 | 7 | ## ‘거의 같음’ 연산자를 문법에 추가하고 AlE타입의 객체를 출력 해보기 8 |

9 | -------------------------------------------------------------------------------- /8th_members/이용준/9주차.md: -------------------------------------------------------------------------------- 1 | ## 10.3.8 애플리케이션 예제의 두 코드를 실행 2 | 3 | ![mission-9-1](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/65945f25-c065-4f81-b854-5f4bc2499a82) 4 | 5 | ![mission-9-2](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/35c382c3-1b37-4bae-9d4c-caa12a6cdabe) 6 | -------------------------------------------------------------------------------- /8th_members/이용준/4주차.md: -------------------------------------------------------------------------------- 1 | # instaviz로 AST 시각화 해보기 2 | 3 | ![mission-4-1](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/ff702cba-07fb-4d2a-b987-835333ef9130) 4 | 5 | # ‘거의 같음’ 연산자를 문법에 추가하고 AlE타입의 객체를 출력 해보기 6 | 7 | ![mission-4-2](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/0905c936-597b-4e30-8cd0-90756b36bfd1) 8 | -------------------------------------------------------------------------------- /8th_members/이용준/2주차.md: -------------------------------------------------------------------------------- 1 | # 컴파일 완료된 화면 캡쳐 (./python.exe 실행 화면) 2 | 3 | ![mission2-1](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/ac0b6879-98c4-4705-9a75-63379bbe9072) 4 | 5 | # 문법 다시 생성하기 (pass 키워드 변경해보기) (결과 화면 캡쳐) 6 | 7 | ![mission2-2](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/4f3d44e2-09bc-4b89-b94a-3510d62ef05c) 8 | -------------------------------------------------------------------------------- /8th_members/전희선/1주차.md: -------------------------------------------------------------------------------- 1 | - CPython 소스코드 다운로드 및 환경 구성 (화면 캡쳐) 2 | image 3 | - 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 등 4 | - CPython 튜토리얼 페이지를 팀원 분들과 함께 완성해나가는 것이 목표입니다! 5 | - 함께 Python 내부 구조를 깊이 있게 알아가서 고급 Python 개발자가 되었으면 좋겠습니다 :) 6 | -------------------------------------------------------------------------------- /8th_members/이용준/3주차.md: -------------------------------------------------------------------------------- 1 | # 파이썬 세션에서 runtime flag 확인하기 2 | 3 | ![mission-3-2](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/b2d4b24f-4418-43ab-9717-bdb328cb5179) 4 | 5 | # importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기 (결과 화면 캡쳐) 6 | 7 | ![mission-3-3](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/d103e7e5-3e56-43dd-8259-20a1a5f5bcaa) 8 | -------------------------------------------------------------------------------- /8th_members/김원경/4주차.md: -------------------------------------------------------------------------------- 1 | # 1. instaviz로 AST 시각화 2 | image 3 |

4 | 5 | # 2. ‘거의 같음’ 연산자를 문법에 추가하고 AlE타입의 객체를 출력 6 | image -------------------------------------------------------------------------------- /8th_members/하상천/1주차.md: -------------------------------------------------------------------------------- 1 | - CPython 소스코드 다운로드 및 환경 구성 2 | image 3 | - 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 4 | - Python의 내부 구조를 깊이 있게 이해하고, CPython 소스코드를 분석해보고 싶습니다. 5 | - CPython 소스코드를 분석하면서, Python의 내부 동작 원리를 이해하고, 이를 통해 Python의 성능을 최적화하는 방법을 배우고 싶습니다. 6 | -------------------------------------------------------------------------------- /8th_members/김원경/3주차.md: -------------------------------------------------------------------------------- 1 | ## 파이썬 세션에서 runtime flag 확인하기 2 | image 3 | 4 | ## importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기 5 | image -------------------------------------------------------------------------------- /8th_members/이성범/3주차.md: -------------------------------------------------------------------------------- 1 | # 3주차 2 | 3 | ## CPython 인터프리터 실행 과정 코드 레벨로 이해하기 4 |

5 | 6 | ## 파이썬 세션에서 runtime flag 확인하기 7 |

8 | 9 | ## importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기 10 |

-------------------------------------------------------------------------------- /8th_members/김필모/1주차.md: -------------------------------------------------------------------------------- 1 | # 1주차 2 | 3 | ## CPython 소스코드 다운로드 및 환경 구성 4 | 5 | Screenshot 2024-03-11 at 11 56 05 PM 6 | 7 | ## 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 8 | 9 | - 한국어로 된 문서 중 가장 좋은 Cpython 문서 만들기!! 10 | - 이제 백준 문제 풀이 시간 순위 1등은 내꺼! 11 | - 어디가서 파이썬 좀 안다 자신있게 말하기 12 | -------------------------------------------------------------------------------- /8th_members/김원경/2주차.md: -------------------------------------------------------------------------------- 1 | # 2주차 2 | 3 | ## 컴파일 완료된 화면 캡쳐 (./python.exe 실행 화면) 4 | image 5 | 6 | 7 | ## 문법 다시 생성하기 (pass 키워드 변경해보기) 부분 원하는 키워드 다른걸로 바꿔보기 8 | image -------------------------------------------------------------------------------- /8th_members/김진아/9주차.md: -------------------------------------------------------------------------------- 1 | # 9주차 2 | 3 | ## Port Scanner: Queue 4 | 스크린샷 2024-06-09 오후 11 10 47 5 | 6 | ## Port Scanner: multiprocessing.Queue 7 | 스크린샷 2024-06-09 오후 11 11 38 8 | -------------------------------------------------------------------------------- /book/c_extension_sample/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup, Extension 2 | 3 | def main(): 4 | setup(name="fputs", 5 | version="1.0.0", 6 | description="Python interface for the fputs C library funtion", 7 | author="kwang1", 8 | author_email="4roring@naver.com", 9 | ext_modules=[Extension("fputs", ["fputsmodule.c"])]) 10 | 11 | 12 | if __name__ == "__main__": 13 | main() 14 | -------------------------------------------------------------------------------- /8th_members/김원경/9주차.md: -------------------------------------------------------------------------------- 1 | ### 10.3.8 애플리케이션 예제 두 코드 실행해보기 2 | 1개 이상의 port가 출력되도록 만들기 위해 검사하는 port 번호 range를 0~99로 변경했습니다.
3 | 4 | 스크린샷 2024-06-03 오후 6 50 35 5 | 스크린샷 2024-06-03 오후 6 33 17 6 | -------------------------------------------------------------------------------- /8th_members/김필모/3주차.md: -------------------------------------------------------------------------------- 1 | # 3주차 2 | 3 | ## 파이썬 세션에서 runtime flag 확인하기 4 | Screenshot 2024-04-13 at 11 51 33 PM 5 | 6 | 7 | ## importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기 8 | Screenshot 2024-04-13 at 11 55 33 PM 9 | -------------------------------------------------------------------------------- /8th_members/김진아/2주차.md: -------------------------------------------------------------------------------- 1 | # 2주차 2 | 3 | ## 컴파일 완료된 화면 캡쳐 (./python.exe 실행 화면) 4 | 스크린샷 2024-03-23 오후 11 31 31 5 | 6 | ## 문법 다시 생성하기 (pass 키워드 변경해보기) 부분 원하는 키워드 다른걸로 바꿔보기 (결과 화면 캡쳐) 7 | 스크린샷 2024-03-23 오후 11 42 18 8 | -------------------------------------------------------------------------------- /8th_members/김진아/1주차.md: -------------------------------------------------------------------------------- 1 | # 1주차 2 | 3 | ## CPython 소스코드 다운로드 및 환경 구성 (화면 캡쳐) 4 | 스크린샷 2024-03-17 오후 11 11 04 5 | 6 | ## 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 등 7 | - Python을 깊이 이해하여 Python을 잘 활용하는 개발자가 되고 싶습니다. 8 | - Python의 내부 구조와 코드를 파악하며 Python의 철학을 이해하고 좋은 코드에 대해서도 배워가고 싶습니다. 9 | - 같이 스터디하면서 많이 배우겠습니다! 재밌고 보람찬 시간이 될 수 있도록 열심히 참여하겠습니다. 10 | -------------------------------------------------------------------------------- /8th_members/하상천/4주차.md: -------------------------------------------------------------------------------- 1 | - instaviz로 AST 시각화 해보기 2 | 3 | image 4 | 5 | image 6 | 7 | - ‘거의 같음’ 연산자를 문법에 추가하고 AlE타입의 객체를 출력 해보기 8 | 9 | ![image](https://github.com/Pseudo-Lab/CPython-Guide/assets/54731898/290ac139-45d7-437f-ac42-bea19213f977) 10 | -------------------------------------------------------------------------------- /8th_members/전희선/2주차.md: -------------------------------------------------------------------------------- 1 | - 컴파일 진행 2 |
image 3 |
image 4 | - Grammar/python.gram 에서 'break'문 키워드에 'end_this_loop' 추가 5 |
image 6 | -------------------------------------------------------------------------------- /book/intro.md: -------------------------------------------------------------------------------- 1 | # CPython Guide for PseudoLab 2 | 3 | 가짜연구소 CPython 파헤치기 스터디팀에서 작성하는 CPython Guide 페이지 입니다. 4 | 5 | ### [CPython Github](https://github.com/python/cpython) 6 | 스터디에 활용되는 CPython Github 저장소 입니다. 7 | 8 | ### CPython 파헤치기 Notion 페이지 9 | 스터디 진행 기록을 저장하는 Notion 페이지 입니다. 10 | - [6기 (2023.03~2023.07)](https://www.notion.so/chanrankim/CPython-868604c8879341808b85d4321bb07501?pvs=4) 11 | - [8기 (2024.03~2024.06)](https://www.notion.so/chanrankim/Python-CPython-eb832e65c4b1443ba3b9be8d5fc5883a?pvs=4) 12 | -------------------------------------------------------------------------------- /8th_members/김원경/7주차.md: -------------------------------------------------------------------------------- 1 | - tracemalloc 통해 직접 메모리 확인해보기 2 | 3 | 아래 레포지토리의 코드(프로그램)를 통해 메모리를 확인해보았습니다.
4 | https://github.com/secureWKkim/web-crawling-on-container 5 |

6 | 7 | 실행 결과는 아래와 같습니다.
8 | 스크린샷 2024-06-03 오후 3 05 44 9 | 스크린샷 2024-06-03 오후 3 05 53 -------------------------------------------------------------------------------- /8th_members/김원경/1주차.md: -------------------------------------------------------------------------------- 1 | ## CPython 소스코드 다운로드 및 환경 구성 (화면 캡쳐) 2 | ![alt text](image.png) 3 |

4 | 5 | ### 특이 사항 6 | 스터디 노션 환경 구성에 나온 정보대로
7 | git clone --branch 3.9 https://github.com/python/cpython 8 |
9 | 명령어만 사용하면 사이즈가 커서 RPC fail 에러 발생.
10 | 그래서 뒤에 "--depth 1" 을 추가로 붙여 얕은 클론만 해둔 상태.
11 | 필요한 경우 "git fetch --unshallow"로 다른 레포들도 갖고 와야 한다.
12 | *참고: https://eunjinii.tistory.com/128 13 |

14 | 15 | 16 | ## 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 등 17 | 그동안 파이썬을 사용하면서 궁금했던 점들을 알아 가며 호기심을 해소할 수 있는 기회가 됐음 합니다! -------------------------------------------------------------------------------- /8th_members/김원경/13주차.md: -------------------------------------------------------------------------------- 1 | # pdb 실행 해보기 2 | image 3 |

4 | 5 | # CProfile 예제 파일 직접 생성해서 실행해보기 6 | 12주차 미션으로 제출한 python game.py 코드를 그대로 사용했습니다. 실행 결과는 아래와 같습니다.
7 | image 8 | image -------------------------------------------------------------------------------- /8th_members/김진아/4주차.md: -------------------------------------------------------------------------------- 1 | # 4주차 2 | 3 | ## instaviz로 AST 시각화 해보기 4 | ```python 5 | def pow(x, y): 6 | result = 1 7 | for i in range(0, y): 8 | result *= x 9 | return result 10 | 11 | import instaviz 12 | instaviz.show(pow) 13 | ``` 14 | ![image](https://github.com/mikaniz/CPython-Guide/assets/92143119/e0462f9b-f336-4813-a585-2cf34f6794bc) 15 | 16 | ## ‘거의 같음’ 연산자를 문법에 추가하고 AlE타입의 객체를 출력 해보기 17 | 스크린샷 2024-04-22 오후 9 55 21 18 | -------------------------------------------------------------------------------- /8th_members/이용준/1주차.md: -------------------------------------------------------------------------------- 1 | # CPython 소스코드 다운로드 및 환경 구성 (화면 캡쳐) 2 | 3 | ![mission-1](https://github.com/Pseudo-Lab/CPython-Guide/assets/48748376/5879640d-708f-4ae0-965a-0d62eb056e4b) 4 | 5 | # 스터디에서 이루고 싶은 목표, 함께 하게 된 소감 등 6 | - 목표 7 | - Python 동작 원리 맛보기 8 | - 스터디 참여자분들과 소통하며 다른 분들의 생각 본받기 9 | - 회사 일이 습격하더라도, 중간에 내용 이해가 어렵더라도 끝까지 완주하기 10 | - 소감 11 | - 개인적으로 진지한 스터디 참여(?)는 처음이고 Cpython을 공부해볼 수 있다니 기대가 됩니다. 하지만 내 실력에 너무 난이도 높은 주제를 선택한 게 아닐까 하는 두려움이 있습니다. 그리고 당장 도움이 안 될 것 같은 내용 가지고 씨름하며 동기부여를 잃어버릴까 걱정도 앞섭니다. 그래서 스터디원분들과 소통하며 서로의 학습과 동기부여의 도우미가 된다면 좋겠습니다. -------------------------------------------------------------------------------- /8th_members/고동희/3주차.md: -------------------------------------------------------------------------------- 1 | # 3주차 2 | 3 | ## [1] CPython 인터프리터 실행 과정 코드 레벨로 이해하기 4 | 5 |
6 | 7 |
8 | 9 | ## [2] 파이썬 세션에서 runtime flag 확인하기 10 | 11 |
12 | 13 |
14 | 15 | ## [3] `importlib.util.find_spec` 함수를 사용해서 원하는 모듈의 위치를 찾아보기 16 | 17 |
18 | 19 |
-------------------------------------------------------------------------------- /8th_members/전희선/8주차.md: -------------------------------------------------------------------------------- 1 | - 라이브러리(requests) import 후 참조 카운트 변화 확인 2 | ```python 3 | >>> import sys 4 | >>> for i in range(1, 4): 5 | ... print(f"{i}: {sys.getrefcount(i)}") 6 | ... 7 | 1: 146 8 | 2: 110 9 | 3: 50 10 | >>> import requests 11 | >>> for i in range(1, 4): 12 | ... print(f"{i}: {sys.getrefcount(i)}") 13 | ... 14 | 1: 1063 15 | 2: 444 16 | 3: 244 17 | ``` 18 | image 19 | -------------------------------------------------------------------------------- /8th_members/김원경/10주차.md: -------------------------------------------------------------------------------- 1 | # Port Scanner: Multi Threading 코드 실행해보기 2 | ## 싱글 프로세스 + 싱글 스레드 3 | image 4 |

5 | 6 | ## 멀티 스레드 7 | image 8 |

9 | 10 | ## 멀티스레딩 + 스레드 개수 제한 11 | image 12 | 근소하게 개선됐다. -------------------------------------------------------------------------------- /8th_members/하상천/3주차.md: -------------------------------------------------------------------------------- 1 | 2 | 1. CPython 인터프리터 실행 과정 코드 레벨로 이해하기 3 | 4 | image 5 | 6 | 2. 파이썬 세션에서 runtime flag 확인하기 7 | 8 | image 9 | 10 | 3. importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기 11 | 12 | image 13 | -------------------------------------------------------------------------------- /8th_members/김진아/3주차.md: -------------------------------------------------------------------------------- 1 | # 3주차 2 | 3 | ## CPython 인터프리터 실행 과정 코드 레벨로 이해하기 4 | 스크린샷 2024-04-07 오후 6 05 05 5 | 6 | ## 파이썬 세션에서 runtime flag 확인하기 7 | 스크린샷 2024-04-07 오후 6 06 29 8 | 9 | 10 | ## importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기 11 | 스크린샷 2024-04-07 오후 6 11 14 12 | 13 | -------------------------------------------------------------------------------- /8th_members/이용우/5주차.md: -------------------------------------------------------------------------------- 1 | ### 요약 2 | 이번 챕터에서는 Parsing된 파이썬 모듈을 3 | 심볼 테이블과 컴파일러 상태로 변환하고 4 | 마지막으로 일련의 바이트코드 명령으로 변환하는 과정에 대해 알아보았다. 5 | 6 | image 7 | 8 | 9 | 바이트코드 명령으로 변환된 모듈을 실행하는 것이 10 | CPython 인터프리터의 코어 평가 루프가 하는 역할이다. 11 | 12 |


13 | 14 | ### 5주차 미션 15 | 이번 장에서는 컴파일러, 바이트코드 명령, 어셈블러를 다뤘다. 16 | 여기서 06. 렉싱과 파싱에서 문법에 추가한 '거의 같음' 연산자를 지원하도록 CPython을 수정해보자. 17 | 18 | image 19 | 20 | -------------------------------------------------------------------------------- /8th_members/김필모/2주차.md: -------------------------------------------------------------------------------- 1 | ## 문법 다시 생성하기 (pass 키워드 변경해보기) 부분 원하는 키워드 다른걸로 바꿔보기 (결과 화면 캡쳐) 2 | ### 1. pass -> do_nothing 3 | Screenshot 2024-03-19 at 5 43 11 AM 4 | 5 | ### 2. break -> stop 6 | Screenshot 2024-03-19 at 6 17 41 AM 7 | 8 | ### lzma.h 을 찾을 수 없다는 에러 9 | Screenshot 2024-03-19 at 6 19 27 AM 10 | 11 | - 맥 기준 brew install xz 하면 해결된다는데 저는 안되네요.. ㅠㅠ 12 | -------------------------------------------------------------------------------- /book/docs/0_1_directory_structure.md: -------------------------------------------------------------------------------- 1 | # CPython 디렉터리 구조 2 | CPython 프로젝트의 디렉터리 구조입니다. 3 | ```yaml 4 | CPython-Guide 5 | ├── Doc # 문서 소스 파일 6 | ├── Grammar # 컴퓨터가 읽을 수 있는 언어 정의 7 | ├── Include # C 헤더 파일 8 | ├── Lib # 파이썬으로 작성된 표준 라이브러리 모듈 9 | ├── Mac # macOS를 위한 파일 10 | ├── Misc # 기타 파일 11 | ├── Modules # C로 작성된 표준 라이브러리 모듈 12 | ├── Objects # 코어 타입과 객체 모델 13 | ├── Parser # 파이썬 파서 소스 코드 14 | ├── PC # 이전 버전 윈도우를 위한 윈도우 빌드 지원 파일 15 | ├── PCbuild # 윈도우 빌드 지원 파일 16 | ├── Python # CPython 인터프리터 소스 코드 17 | ├── Tools # CPython을 빌드하거나 확장하는 데 유용한 독립 실행형 도구 18 | └── m4 # makefile 구성을 자동화하는 사용자화 스크립트 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /8th_members/이용우/13주차.md: -------------------------------------------------------------------------------- 1 | ### 1. pdb 실행 2 | 3 | |shortcut|설명| 4 | |---|---| 5 | |`l`|주변 소스코드를 출력하며 현재 라인이 화살표로 나옴| 6 | |`n`|다음 문장으로 이동| 7 | |`s`|Step Into| 8 | |`w`|함수의 call stack 출력| 9 | |`s`|현재 함수의 argument들을 출력| 10 | 11 | 12 | 13 |


14 | 15 | ### 2. CProfile 예제 파일 직접 생성해서 실행해보기 16 | 17 | ``` bash 18 | $ python -m cProfile -o output.pstat portscanner_multithread.py 19 | ``` 20 | 21 | 22 | 23 | 24 |
25 | 26 | ``` bash 27 | $ pip install snakeviz 28 | $ python -m snakeviz output.pstat 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /8th_members/하상천/12주차.md: -------------------------------------------------------------------------------- 1 | ## 나만의 Test Case 만들기 2 | 3 | ```python 4 | import unittest 5 | import re 6 | 7 | korean = re.compile(r"[가-힣]") 8 | 9 | 10 | class TestPreprocess(unittest.TestCase): 11 | def test_korean(self): 12 | self.assertTrue(korean.match("한글")) 13 | self.assertFalse(korean.match("english")) 14 | self.assertFalse(korean.match("1234")) 15 | self.assertFalse(korean.match("!@#$")) 16 | self.assertTrue(korean.match("한글english1234!@#$")) 17 | ``` 18 | 19 | ```bash 20 | python -m unittest discover tests -v 21 | python -m unittest tests.test_preprocess -v 22 | python -m unittest tests.test_preprocess.TestPreprocess -v 23 | python -m unittest tests.test_preprocess.TestPreprocess.test_korean -v 24 | ``` 25 | 26 | image 27 | -------------------------------------------------------------------------------- /8th_members/이성범/9주차.md: -------------------------------------------------------------------------------- 1 | # 9주차 2 | 3 | ## 간단한 CPU-Bound Job을 만들고 멀티프로세싱을 적용한 코드와 아닌 코드를 작성해보기 4 | ```python 5 | import time 6 | import multiprocessing as mp 7 | 8 | pool_size = 10 9 | 10 | def cpu_task(a=1): 11 | time.sleep(1) 12 | 13 | def no_multiprocessing_run(): 14 | start_time = time.time() 15 | for _ in range(pool_size): 16 | cpu_task() 17 | end_time = time.time() 18 | print(f"Duration without multiprocessing: {end_time - start_time} seconds") 19 | 20 | def multiprocessing_run(): 21 | start_time = time.time() 22 | with mp.Pool(pool_size) as p: 23 | p.map(cpu_task, range(pool_size)) 24 | end_time = time.time() 25 | print(f"Duration with multiprocessing: {end_time - start_time} seconds") 26 | 27 | if __name__ == '__main__': 28 | no_multiprocessing_run() 29 | multiprocessing_run() 30 | ``` 31 |

-------------------------------------------------------------------------------- /book/c_extension_sample/fputsmodule.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static PyObject* method_fputs(PyObject* self, PyObject* args) { 4 | char *str, *filename = NULL; 5 | int bytes_copied = -1; 6 | 7 | if(!PyArg_ParseTuple(args, "ss", &str, &filename)) { 8 | return NULL; 9 | } 10 | 11 | FILE *fp = fopen(filename, "w"); 12 | bytes_copied = fputs(str, fp); 13 | fclose(fp); 14 | 15 | return PyLong_FromLong(bytes_copied); 16 | } 17 | 18 | static PyMethodDef FPutsMethods[] = { 19 | {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"}, 20 | {NULL, NULL, 0, NULL} 21 | }; 22 | 23 | static struct PyModuleDef fputsmodule = { 24 | PyModuleDef_HEAD_INIT, 25 | "fputs", 26 | "Python interface for the fputs C library function", 27 | -1, 28 | FPutsMethods 29 | }; 30 | 31 | PyMODINIT_FUNC PyInit_fputs(void) { 32 | return PyModule_Create(&fputsmodule); 33 | } 34 | -------------------------------------------------------------------------------- /8th_members/김진아/7주차.md: -------------------------------------------------------------------------------- 1 | # 7주차 2 | 3 | ## tracemalloc 모듈 사용해서 직접 메모리 확인해보기 4 | ```python 5 | import tracemalloc 6 | 7 | 8 | def fac_with_recursion(n): 9 | if n <= 1: 10 | return n 11 | return n * fac_with_recursion(n - 1) 12 | 13 | 14 | def fac_with_loop(n): 15 | result = 1 16 | for i in range(1, n): 17 | result *= i 18 | return result 19 | 20 | 21 | tracemalloc.start() 22 | 23 | fac_10_with_recursion = fac_with_recursion(10) 24 | fac_10_with_loop = fac_with_loop(10) 25 | 26 | snapshot = tracemalloc.take_snapshot() 27 | snapshot = snapshot.filter_traces([tracemalloc.Filter(True, "**/tracemalloc_example.py")]) 28 | stats = snapshot.statistics("lineno") 29 | 30 | for stat in stats: 31 | print(stat, stat.traceback.format()) 32 | 33 | tracemalloc.stop() 34 | ``` 35 | 스크린샷 2024-05-21 오전 12 27 46 36 | -------------------------------------------------------------------------------- /book/docs/sample/markdown-example.md: -------------------------------------------------------------------------------- 1 | # markdown 샘플 2 | 3 | Jupyter Book은 markdown 문서를 지원합니다. 4 | 5 | 아래와 같은 예시 코드를 입력하면 markdown 문법이 적용됩니다. 6 | 7 | ``` 8 | # This is an h1 tag 9 | ## This is an h2 tag 10 | ###### This is an h6 tag 11 | 12 | *This text will be italic* 13 | _This will also be italic_ 14 | 15 | **This text will be bold** 16 | __This will also be bold__ 17 | 18 | _You **can** combine them_ 19 | 20 | * Item 1 21 | * Item 2 22 | * Item 2a 23 | * Item 2b 24 | 25 | 1. Item 1 26 | 1. Item 2 27 | 1. Item 3 28 | 1. Item 3a 29 | 1. Item 3b 30 | ``` 31 | 32 | 입력 결과 33 | 34 | # This is an h1 tag 35 | ## This is an h2 tag 36 | ###### This is an h6 tag 37 | 38 | *This text will be italic* 39 | _This will also be italic_ 40 | 41 | **This text will be bold** 42 | __This will also be bold__ 43 | 44 | _You **can** combine them_ 45 | 46 | * Item 1 47 | * Item 2 48 | * Item 2a 49 | * Item 2b 50 | 51 | 1. Item 1 52 | 1. Item 2 53 | 1. Item 3 54 | 1. Item 3a 55 | 1. Item 3b -------------------------------------------------------------------------------- /8th_members/김진아/6주차.md: -------------------------------------------------------------------------------- 1 | # 6주차 2 | 3 | ## 파이썬에서 프레임 객체 접근해보기 4 | ```python 5 | import inspect 6 | 7 | 8 | def print_frame_info(): 9 | frame = inspect.currentframe().f_back 10 | try: 11 | print("Function Name:", frame.f_code.co_name) 12 | print("File Name:", frame.f_code.co_filename) 13 | print("Line No:", frame.f_back.f_lineno) 14 | print("Local Variables:", list(frame.f_locals.keys())) 15 | print("Global Variables:", list(frame.f_globals.keys())) 16 | finally: 17 | del frame 18 | 19 | 20 | def print_sum(n1, n2): 21 | sum = n1 + n2 22 | print(sum) 23 | print_frame_info() 24 | 25 | 26 | def print_upper(word): 27 | upper_word = word.upper() 28 | print(upper_word) 29 | print_frame_info() 30 | 31 | 32 | print_sum(10, 20) 33 | print_upper("Python") 34 | ``` 35 | 스크린샷 2024-05-12 오후 8 14 24 36 | -------------------------------------------------------------------------------- /8th_members/전희선/6주차.md: -------------------------------------------------------------------------------- 1 | ### 파이썬에서 프레임 객체 접근해보기 2 | ```python 3 | import inspect 4 | import requests 5 | import dis 6 | 7 | def print_frame_info(): 8 | frame = inspect.currentframe().f_back # 현재 함수의 호출자 프레임 9 | try: 10 | print("Function Name:", frame.f_code.co_name) 11 | print("File Name:", frame.f_code.co_filename) 12 | print("Line No:", frame.f_back.f_lineno) 13 | print("Local Variables:", list(frame.f_locals.keys())) 14 | print("Global Variables:", list(frame.f_globals.keys())) 15 | dis.dis(frame.f_code) # 역 디스어셈블러 16 | print() 17 | finally: 18 | del frame 19 | 20 | def request_get(url): 21 | requests.get(url) 22 | print_frame_info() 23 | 24 | def request_post(url): 25 | requests.post(url) 26 | print_frame_info() 27 | 28 | request_get("https://naver.com") 29 | request_post("https://naver.com") 30 | ``` 31 | image 32 | -------------------------------------------------------------------------------- /book/_toc.yml: -------------------------------------------------------------------------------- 1 | format: jb-book 2 | root: intro 3 | parts: 4 | - caption: ◽ CPython 가이드 5 | chapters: 6 | # - file: docs/0_0_dev_env_setup 7 | # sections: 8 | # - file: docs/0_1_directory_structure 9 | - file: docs/1_0_welcome_to_cpython 10 | - file: docs/2_0_settings 11 | - file: docs/3_0_compile 12 | - file: docs/4_0_python_grammar 13 | - file: docs/5_0_config_and_input 14 | - file: docs/6_0_rexing_and_parsing 15 | - file: docs/7_0_compiler 16 | - file: docs/8_0_eval_loop 17 | - file: docs/9_0_memory 18 | sections: 19 | - file: docs/9_1_memory_pool 20 | - file: docs/9_2_garbage_collection 21 | - file: docs/10_0_parallel_and_concurrent 22 | sections: 23 | - file: docs/10_1_process 24 | - file: docs/10_2_thread 25 | - file: docs/10_3_async 26 | - file: docs/11_0_object_and_type 27 | - file: docs/12_0_standard_library 28 | - file: docs/13_0_test_suite 29 | - file: docs/14_0_c_extension 30 | 31 | #- caption: ◽ 샘플 32 | # - file: docs/sample/markdown-example 33 | # - file: docs/sample/notebook-example 34 | -------------------------------------------------------------------------------- /8th_members/전희선/7주차.md: -------------------------------------------------------------------------------- 1 | - tracemalloc 통해 직접 메모리 확인해보기 2 | ```python 3 | import tracemalloc 4 | import linecache 5 | import requests 6 | 7 | def request_get(url): 8 | result = requests.get(url) 9 | return result 10 | 11 | def request_post(url): 12 | result = requests.post(url) 13 | return result 14 | 15 | def main(): 16 | tracemalloc.start() 17 | result_get = request_get("https://naver.com") 18 | result_post = request_post("https://naver.com") 19 | 20 | snapshot = tracemalloc.take_snapshot() 21 | snapshot = snapshot.filter_traces(( 22 | tracemalloc.Filter(True, "*/requests/*"), 23 | )) 24 | stats = snapshot.statistics("lineno") 25 | 26 | for stat in stats[:10]: 27 | frame = stat.traceback[0] 28 | print(f"{frame.filename}:{frame.lineno} - {stat.size} bytes") 29 | print("\t" + linecache.getline(frame.filename, frame.lineno).strip()) 30 | 31 | tracemalloc.stop() 32 | 33 | main() 34 | ``` 35 | image 36 | -------------------------------------------------------------------------------- /8th_members/전희선/4주차.md: -------------------------------------------------------------------------------- 1 | - instaviz로 AST 시각화 해보기 2 | ```python 3 | def add_and_subtract(a, b): 4 | add_result = a + b 5 | subtract_result = a - b 6 | return add_result, subtract_result 7 | 8 | import instaviz 9 | instaviz.show(add_and_subtract) 10 | ``` 11 | ![image](https://github.com/heehehe/CPython-Guide/assets/41580746/7f8455e4-cdd2-43b4-9db8-ef23479f72c6) 12 | - ‘거의 같음’ 연산자를 문법에 추가하고 ALE 타입의 객체를 출력 해보기 13 |
image 14 |
image 15 |
image 16 |
image 17 | ``` 18 | make regen-token regen-pegen 19 | make regen-ast 20 | make -j2 -s 21 | ``` 22 | -------------------------------------------------------------------------------- /8th_members/이용우/7주차.md: -------------------------------------------------------------------------------- 1 | ### 미션 - tracemalloc 모듈을 사용해서 직접 메모리 확인해보기 2 | - tracemalloc 모듈을 통해 객체 할당자의 메모리 할당 동작 디버깅이 가능하다. 3 | - tracemalloc 모듈은 객체 할당 위치, 할당된 메모리 블록 개수 등을 제공해준다. 4 | - 코드 실행 시 사용되는 메모리 양을 예상, 메모리 누수를 감지할 수 있다. 5 | 6 | python 실행 시 `-X tracemalloc=[추적할 프레임 수]` 옵션 추가하여 실행시킬 수 있다. 7 | - `take_snapshot()`: 스냅샷 인스턴스 생성 8 | - `compare_to()`: 호출 → 여러 스냅샷 비교 9 | 10 | 11 |

12 | 13 | ``` python 14 | import tracemalloc 15 | 16 | 17 | tracemalloc.start() 18 | value = "1" 19 | string_value = [value for _ in range(1000)] 20 | float_value = [float(value) for _ in range(1000)] 21 | int_value = [int(value) for _ in range(1000)] 22 | 23 | # 스냅샷 시작 24 | snapshot1 = tracemalloc.take_snapshot() 25 | snapshot1 = snapshot1.filter_traces([tracemalloc.Filter(True, "**/stat_*.py")]) 26 | stats = snapshot1.statistics("lineno") 27 | 28 | for stat in stats: 29 | print(stat) 30 | print(stat.traceback.format(), end='\n\n') 31 | 32 | # 스냅샷 종료 33 | tracemalloc.stop() 34 | ``` 35 | 36 | -------------------------------------------------------------------------------- /8th_members/김필모/13주차.md: -------------------------------------------------------------------------------- 1 | # pdb 실행 해보기 2 | 3 | Screenshot 2024-06-30 at 5 23 18 PM 4 | 5 | 6 | 7 | # CProfile 예제 직접 실행해보기 8 | 9 | ```python3 10 | # example.py 11 | 12 | import cProfile 13 | import pstats 14 | import io 15 | 16 | def slow_function(): 17 | total = 0 18 | for i in range(10000): 19 | for j in range(10000): 20 | total += i * j 21 | return total 22 | 23 | def fast_function(): 24 | return sum(i * j for i in range(1000) for j in range(1000)) 25 | 26 | def main(): 27 | slow_function() 28 | fast_function() 29 | 30 | if __name__ == '__main__': 31 | pr = cProfile.Profile() 32 | pr.enable() 33 | main() 34 | pr.disable() 35 | 36 | s = io.StringIO() 37 | sortby = 'cumulative' 38 | ps = pstats.Stats(pr, stream=s).sort_stats(sortby) 39 | ps.print_stats() 40 | print(s.getvalue()) 41 | 42 | ``` 43 | Screenshot 2024-06-30 at 5 31 22 PM 44 | -------------------------------------------------------------------------------- /8th_members/김필모/9주차.md: -------------------------------------------------------------------------------- 1 | ```python3 2 | import time 3 | from multiprocessing import Pool 4 | 5 | # Define the CPU-bound task 6 | 7 | 8 | def cpu_bound_task(n): 9 | result = 1 10 | for i in range(1, n + 1): 11 | result *= i 12 | return result 13 | 14 | # Single-process version 15 | 16 | 17 | def single_process(tasks): 18 | results = [] 19 | for task in tasks: 20 | results.append(cpu_bound_task(task)) 21 | return results 22 | 23 | # Multiprocessing version 24 | 25 | 26 | def multi_process(tasks): 27 | with Pool() as pool: 28 | results = pool.map(cpu_bound_task, tasks) 29 | return results 30 | 31 | 32 | if __name__ == "__main__": 33 | tasks = [100000 + i for i in range(20)] # Define tasks 34 | 35 | start = time.time() 36 | single_process(tasks) 37 | print("Single-process time:", time.time() - start) 38 | 39 | start = time.time() 40 | multi_process(tasks) 41 | print("Multiprocessing time:", time.time() - start) 42 | ``` 43 | Screenshot 2024-06-30 at 2 18 40 PM 44 | 45 | -------------------------------------------------------------------------------- /8th_members/김필모/4주차.md: -------------------------------------------------------------------------------- 1 | - instaviz로 AST 시각화 해보기 2 | 3 | ```python3 4 | def scramble_word(word): 5 | word_list = list(word) 6 | random.shuffle(word_list) 7 | return ''.join(word_list) 8 | ``` 9 | 10 | Screenshot 2024-04-16 at 2 38 25 PM 11 | Screenshot 2024-04-16 at 2 39 00 PM 12 | Screenshot 2024-04-16 at 2 39 28 PM 13 | Screenshot 2024-04-16 at 2 39 38 PM 14 | 15 | 16 | - ‘거의 같음’ 연산자를 문법에 추가하고 ALE 타입의 객체를 출력 해보기 17 | 18 | Screenshot 2024-04-16 at 2 41 26 PM 19 | 20 | ```shell 21 | make regen-token regen-pegen 22 | make regen-ast 23 | make -j2 -s 24 | ``` 25 | 26 | -------------------------------------------------------------------------------- /book/docs/10_0_parallel_and_concurrent.md: -------------------------------------------------------------------------------- 1 | # 10. 병렬성과 동시성 2 | 3 | ## 개요 4 | 5 | 모든 운영체제의 핵심 기능은 실행 중인 프로세스를 관리하는 것이다. 6 | 모든 프로세스는 메모리와 CPU 같은 자원을 요청할 수 있다. 7 | 8 | **프로세스는 작업 단위로 실행**되기 때문에 CPU에 자신이 사용할 시간을 요청한다. 9 | 이 요쳥을 받은 운영체제는 시간을 프로세스에 할당해주고 우선순위에 따라 스케줄링하며 10 | 어떤 프로세스가 CPU를 사용할지를 컨트롤한다. 11 | 12 | ![concurrent](../images/10_parallel_and_concurrent/concurrency.png) 13 | 14 | 동시성은 멀티태스킹 구현에 알맞은 해결책이긴 하지만 15 | CPU를 나눠쓰기 때문에 한계가 있다. 16 | 17 | ![parallel](../images/10_parallel_and_concurrent/parallel.png) 18 | 19 | 때문에 여러 개의 코어 또는 CPU를 사용해 작업을 분산하는 방식으로 20 | 멀티태스킹을 수행하는 방법도 OS가 제공해준다. 21 | 22 | 즉, 컴퓨터는 병렬성과 동시성을 활용해 멀티태스킹을 처리한다. 23 | 24 | - 병렬성 → CPU와 같은 연산 유닛들이 여러 개 필요 25 | - 동시성 → 유휴 상태의 프로세스가 하나의 자원을 계속해서 차지하지 않도록 스케줄링 필요 26 | 27 | ## 병렬성과 동시성 모델 28 | 29 | CPython은 병렬성과 동시성에 대해 다양한 접근 방식을 제공한다. 30 | 기본적으로 아래의 4가지 모델을 제공한다. 31 | 32 | | 접근 방식 | 모델명 | 동시 실행 | 병렬 실행 | 33 | | -------------- | --------------- | --------- | --------- | 34 | | 쓰레딩 | threading | O | X | 35 | | 멀티프로세싱 | multiprocessing | O | O | 36 | | 비동기 | asyncio | O | X | 37 | | 서브인터프리터 | subinterpreters | O | O | 38 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: deploy-book 2 | 3 | # Only run this when the master branch changes 4 | on: 5 | push: 6 | branches: 7 | - master 8 | # If your git repository has the Jupyter Book within some-subfolder next to 9 | # unrelated files, you can make this run only if a file within that specific 10 | # folder has been modified. 11 | # 12 | # paths: 13 | # - some-subfolder/** 14 | 15 | # This job installs dependencies, builds the book, and pushes it to `gh-pages` 16 | jobs: 17 | deploy-book: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v2 21 | 22 | # Install dependencies 23 | - name: Set up Python 3.8 24 | uses: actions/setup-python@v2 25 | with: 26 | python-version: 3.8 27 | 28 | - name: Install dependencies 29 | run: | 30 | pip install -r requirements.txt 31 | 32 | # Build the book 33 | - name: Build the book 34 | run: | 35 | jupyter-book build ./book 36 | 37 | # Push the book's HTML to github-pages 38 | - name: GitHub Pages action 39 | uses: peaceiris/actions-gh-pages@v3.6.1 40 | with: 41 | github_token: ${{ secrets.GITHUB_TOKEN }} 42 | publish_dir: ./book/_build/html 43 | -------------------------------------------------------------------------------- /8th_members/이성범/10주차.md: -------------------------------------------------------------------------------- 1 | # 10주차 2 | 3 | ## Port Scanner: Multi Threading - 멀티스레딩 + 스레드 개수 제한 4 | ```python 5 | import time 6 | import socket 7 | from concurrent.futures import ThreadPoolExecutor, as_completed 8 | 9 | timeout = 1.0 10 | 11 | def check_port(host: str, port: int) -> int: 12 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 13 | sock.settimeout(timeout) 14 | result = sock.connect_ex((host, port)) 15 | if result == 0: 16 | return port 17 | return None 18 | 19 | def main(): 20 | start = time.time() 21 | host = "localhost" # Replace with a host you own 22 | open_ports = [] 23 | 24 | with ThreadPoolExecutor(max_workers=10) as executor: 25 | futures = [executor.submit(check_port, host, port) for port in range(100, 200)] 26 | 27 | for future in as_completed(futures): 28 | port = future.result() 29 | if port is not None: 30 | open_ports.append(port) 31 | 32 | for port in open_ports: 33 | print(f"Port {port} is open") 34 | print(f"Completed scan in {time.time() - start:.2f} seconds") 35 | 36 | if __name__ == '__main__': 37 | main() 38 | ``` 39 |

-------------------------------------------------------------------------------- /8th_members/김원경/6주차.md: -------------------------------------------------------------------------------- 1 | ## 1. 사용한 코드 2 | ```python 3 | import inspect 4 | 5 | def minBitFlips3(start: int, goal: int) -> int: 6 | flips, xor = 0, start ^ goal 7 | while xor != 0: 8 | flips += 1 9 | xor &= (xor - 1) 10 | print_frame_info() 11 | return flips 12 | 13 | 14 | 15 | def minBitFlips4(start: int, goal: int) -> int: 16 | x = start ^ goal 17 | count = 0 18 | while x: 19 | x = x & (x - 1) 20 | count += 1 21 | print_frame_info() 22 | return count 23 | 24 | 25 | def print_frame_info(): 26 | frame = inspect.currentframe().f_back # 현재 함수의 호출자 프레임 27 | try: 28 | print("Function Name:", frame.f_code.co_name) 29 | print("File Name:", frame.f_code.co_filename) 30 | print("Line No:", frame.f_back.f_lineno) 31 | print("Local Variables:", list(frame.f_locals.keys())) 32 | print("Global Variables:", list(frame.f_globals.keys())) 33 | # dis.dis(frame.f_code) # 역 디스어셈블러 34 | print("\\n\\n") 35 | finally: 36 | del frame 37 | 38 | 39 | minBitFlips3(1, 10) 40 | minBitFlips4(1, 10) 41 | ``` 42 |
43 | 44 | ## 2. 실행 결과 45 | image -------------------------------------------------------------------------------- /8th_members/이용우/10주차.md: -------------------------------------------------------------------------------- 1 | ### 멀티 쓰레드 요약 2 | 1. 각 쓰레드는 각자의 Program Counter와 Stack을 갖기 때문에 3 | 동시에 다른 작업을 처리할 수 있다. 4 | 2. **Thread Safety**를 위해서 CPython에서는 GIL을 사용한다. 5 | 3. GIL로 인해서 CPU-Bound 작업에서는 멀티 쓰레드의 이점을 얻지 못하지만, 6 | I/O-Bound 작업에서는 멀티 쓰레딩을 적극적으로 활용할 수 있다. 7 | 4. 이를 위해서 `Py_BEGIN_ALLOW_THREADS`와 `Py_END_ALLOW_THREADS` 8 | 매크로가 실제 구현에 사용된다. 내장 패키지 구석구석에서 해당 구현을 확인할 수 있다. 9 | 5. Thread는 프로세스와 메모리를 공유하기 때문에 10 | 프로세스를 새로 생성하는 것 보다는 오버헤드가 적다. 11 | 12 | 13 |

14 | 15 | #### 코루틴 16 | → 실행을 중단하고 재개할 수 있는 함수, 특정 시점에서 작업을 중단하고 다른 작업을 수행할 수 있다. 17 | → 호출자와 호출된 함수 사이의 제어 흐름이 상호작용 18 | → 비동기 프로그래밍에서 사용 19 | 20 |
21 | 22 | #### 네이티브 코루틴 23 | - 함수 앞에 `async` 키워드를 명시하여 코루틴을 반환함을 명시 24 | - `asyncio.run()`을 통해 코루틴 객체 생성 25 | - 실행 순서 26 | - 1) 새 이벤트 루프를 시작 27 | - 2) 코루틴 객체를 Task로 감싸기 28 | - 3) Task가 완료될 때 까지 실행할 CallBack을 설정 29 | - 4) Task가 완료될 때 까지 루프를 반복 30 | - 5) 결과 반환 31 | 32 | 장점 33 | - 여러 코루틴 동시 실행 가능 34 | - 코루틴 객체를 다른 함수의 인자로 사용 가능 35 | - 코루틴 객체를 서로 연결하여 연쇄적으로 처리하거나 순차적으로 생성 가능 36 | 37 | ※ 이벤트 루프 38 | - 비동기 코드를 연결하는 접착제 역할 39 | 40 | 41 |


42 | 43 | ### Port Scanner 예제 실행 44 | 45 | 좌: 멀티 쓰레드, 우: 멀티 쓰레드(쓰레드 수 제한) 46 | 47 | -------------------------------------------------------------------------------- /8th_members/김필모/12주차.md: -------------------------------------------------------------------------------- 1 | 2 | # 나만의 Test Case 만들기 3 | 4 | ```python3 5 | def is_prime(n): 6 | """ 7 | Check if a number is a prime number. 8 | 9 | Parameters: 10 | n (int): The number to check. 11 | 12 | Returns: 13 | bool: True if n is a prime number, False otherwise. 14 | """ 15 | if n <= 1: 16 | return False 17 | if n <= 3: 18 | return True 19 | if n % 2 == 0 or n % 3 == 0: 20 | return False 21 | i = 5 22 | while i * i <= n: 23 | if n % i == 0 or n % (i + 2) == 0: 24 | return False 25 | i += 6 26 | return True 27 | 28 | 29 | # Example usage: 30 | if __name__ == "__main__": 31 | print(is_prime(29)) # Expected output: True 32 | print(is_prime(15)) # Expected output: False 33 | ``` 34 | 35 | 36 | ``` 37 | import unittest 38 | 39 | from src import example 40 | 41 | 42 | class TestIsPrime(unittest.TestCase): 43 | def test_is_prime(self): 44 | self.assertEqual(example.is_prime(2), True) 45 | self.assertEqual(example.is_prime(3), True) 46 | self.assertEqual(example.is_prime(4), False) 47 | self.assertEqual(example.is_prime(5), True) 48 | self.assertEqual(example.is_prime(7), True) 49 | 50 | ``` 51 | Screenshot 2024-06-30 at 5 16 31 PM 52 | 53 | 54 | -------------------------------------------------------------------------------- /8th_members/김필모/7주차.md: -------------------------------------------------------------------------------- 1 | 2 | ## 코드 3 | ```python 4 | import tracemalloc 5 | import linecache 6 | import random 7 | import numpy as np 8 | 9 | def memory_intensive_function(size): 10 | data = [random.randint(1, 1000000) for _ in range(size)] 11 | sorted_data = sorted(data) 12 | mid_index = len(sorted_data) // 2 13 | return sorted_data[mid_index] 14 | 15 | 16 | def matrix_multiply(size): 17 | # size x size 크기의 무작위 행렬 두 개 생성 18 | matrix1 = np.random.rand(size, size) 19 | matrix2 = np.random.rand(size, size) 20 | # 두 행렬의 곱 계산 21 | product = np.dot(matrix1, matrix2) 22 | return product 23 | 24 | 25 | def main(): 26 | tracemalloc.start() 27 | x = memory_intensive_function(100000) 28 | y = matrix_multiply(100) 29 | snapshot = tracemalloc.take_snapshot() 30 | snapshot = snapshot.filter_traces(( 31 | tracemalloc.Filter(True, "**/tracedemo.py"), 32 | )) 33 | stats = snapshot.statistics("lineno") 34 | 35 | for stat in stats: 36 | frame = stat.traceback[0] 37 | print(stat) 38 | print(linecache.getline(frame.filename, frame.lineno).strip()) 39 | 40 | tracemalloc.stop() 41 | 42 | 43 | if __name__ == "__main__": 44 | main() 45 | ``` 46 | 47 | 48 | ## 결과 스크린샷 49 | Screenshot 2024-05-20 at 8 23 20 PM 50 | 51 | -------------------------------------------------------------------------------- /8th_members/김진아/13주차.md: -------------------------------------------------------------------------------- 1 | # 13주차 2 | 3 | ## pbd 실행해보기 4 | 5 | ```python 6 | def calculate_performance_improvement_rate(before, after): 7 | return (before - after) / after * 100 8 | 9 | 10 | if __name__ == "__main__": 11 | breakpoint() 12 | 13 | before_performance = 150 14 | after_performance = 57 15 | 16 | performance_improvement_rate = calculate_performance_improvement_rate(before_performance, after_performance) 17 | 18 | print(f"{performance_improvement_rate:.2f}%") 19 | 20 | ``` 21 | 22 | 스크린샷 2024-06-30 오후 3 02 32 23 | 24 | 25 | ## CProfile 예제 파일 직접 생성해서 실행해보기 26 | 27 | ```python 28 | def calculate_performance_improvement_rate(before, after): 29 | return (before - after) / after * 100 30 | 31 | 32 | if __name__ == "__main__": 33 | before_performance = 150 34 | after_performance = 57 35 | 36 | performance_improvement_rate = calculate_performance_improvement_rate(before_performance, after_performance) 37 | 38 | print(f"{performance_improvement_rate:.2f}%") 39 | ``` 40 | 41 | 스크린샷 2024-06-30 오후 3 05 17 42 | 43 | 스크린샷 2024-06-30 오후 3 06 17 44 | -------------------------------------------------------------------------------- /8th_members/하상천/9주차.md: -------------------------------------------------------------------------------- 1 | ## 9주차 미션 2 | 3 | ### Queue 사용 4 | 5 | image 6 | 7 | ### multiprocessing.Queue 사용 8 | 9 | ```python 10 | import multiprocessing as mp 11 | import socket 12 | import time 13 | 14 | timeout = 1.0 15 | 16 | 17 | def check_port(host: str, port: int, results: mp.Queue): 18 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 19 | sock.settimeout(timeout) 20 | result = sock.connect_ex((host, port)) 21 | if result == 0: 22 | results.put(port) 23 | sock.close() 24 | 25 | 26 | if __name__ == '__main__': 27 | start = time.time() 28 | processes = [] 29 | scan_range = range(80, 100) 30 | host = "localhost" 31 | mp.set_start_method('spawn') 32 | pool_manager = mp.Manager() 33 | with mp.Pool(len(scan_range)) as pool: 34 | outputs = pool_manager.Queue() 35 | for port in scan_range: 36 | processes.append(pool.apply_async(check_port, (host, port, outputs))) 37 | for process in processes: 38 | process.get() 39 | while not outputs.empty(): 40 | print("Port {0} is open.".format(outputs.get())) 41 | print("Completed scan in {0} seconds".format(time.time() - start)) 42 | ``` 43 | 44 | image 45 | -------------------------------------------------------------------------------- /book/_config.yml: -------------------------------------------------------------------------------- 1 | ####################################################################################### 2 | # Book settings 3 | title : PseudoLab [CPython 파헤치기] 4 | author: PseudoLab 5 | logo: 'PseudoLab_logo.png' 6 | 7 | # Short description about the book 8 | description: >- 9 | CPython Guide for PseudoLab studies 10 | 11 | ####################################################################################### 12 | # Execution settings 13 | execute: 14 | execute_notebooks : off 15 | 16 | ####################################################################################### 17 | # HTML-specific settings 18 | html: 19 | home_page_in_navbar : false 20 | 21 | # ####################################################################################### 22 | # Interact link settings 23 | notebook_interface : "notebook" 24 | 25 | ####################################################################################### 26 | # Launch button settings 27 | repository: 28 | url : https://github.com/pseudo-lab/CPython-Guide 29 | path_to_book : "book" 30 | 31 | latex: 32 | latex_engine : "xelatex" 33 | latex_documents: 34 | targetname: book.tex 35 | 36 | html: 37 | favicon: 'PseudoLab_logo.png' 38 | use_issues_button: true 39 | use_repository_button: true 40 | 41 | sphinx: 42 | config: 43 | html_js_files: 44 | - https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js 45 | -------------------------------------------------------------------------------- /8th_members/전희선/9주차.md: -------------------------------------------------------------------------------- 1 | 간단한 CPU-Bound Job을 만들고 멀티프로세싱을 적용한 코드와 아닌 코드를 작성해보기 2 | 3 | ```python 4 | from math import sqrt 5 | import time 6 | import multiprocessing as mp 7 | import sys 8 | 9 | NUMBERS_LIMIT = 100000000 10 | 11 | def compute_sqrt(numbers): 12 | return [sqrt(n) for n in numbers] 13 | 14 | def multiprocessing_compute(): 15 | numbers = range(1, NUMBERS_LIMIT) 16 | process_count = mp.cpu_count() # 사용 가능한 CPU 코어 수 17 | pool = mp.Pool(process_count) 18 | 19 | # 데이터 분할 20 | size = len(numbers) // process_count 21 | numbers_split = [numbers[i * size:(i + 1) * size] for i in range(process_count)] 22 | 23 | start_time = time.time() 24 | results = pool.map(compute_sqrt, numbers_split) 25 | end_time = time.time() 26 | pool.close() 27 | pool.join() 28 | print(f"Duration with multiprocessing: {end_time - start_time} seconds") 29 | 30 | 31 | def no_multiprocessing(): 32 | numbers = range(1, NUMBERS_LIMIT) 33 | start_time = time.time() 34 | results = compute_sqrt(numbers) 35 | end_time = time.time() 36 | print(f"Duration without multiprocessing: {end_time - start_time} seconds") 37 | 38 | 39 | if __name__ == '__main__': 40 | option = sys.argv[1] 41 | if option == "multiprocessing": 42 | multiprocessing_compute() 43 | else: 44 | no_multiprocessing() 45 | ``` 46 | 47 | image 48 | -------------------------------------------------------------------------------- /8th_members/김필모/6주차.md: -------------------------------------------------------------------------------- 1 | ```python3 2 | import inspect 3 | import re 4 | 5 | 6 | def print_frame_info(): 7 | frame = inspect.currentframe().f_back # 현재 함수의 호출자 프레임 8 | try: 9 | print("Function Name:", frame.f_code.co_name) 10 | print("File Name:", frame.f_code.co_filename) 11 | print("Line No:", frame.f_back.f_lineno) 12 | print("Local Variables:", list(frame.f_locals.keys())) 13 | print("Global Variables:", list(frame.f_globals.keys())) 14 | # dis.dis(frame.f_code) # 역 디스어셈블러 15 | print("\\n\\n") 16 | finally: 17 | del frame 18 | 19 | 20 | def validate_email(email): 21 | pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" 22 | if re.match(pattern, email): 23 | print_frame_info() 24 | 25 | return True 26 | else: 27 | print_frame_info() 28 | 29 | return False 30 | 31 | 32 | def check_password_complexity(password): 33 | if (len(password) >= 8 and 34 | any(c.isupper() for c in password) and 35 | any(c.islower() for c in password) and 36 | any(c.isdigit() for c in password) and 37 | any(c in '!@#$%^&*()-_=+[]{}|;:",.<>?`~' for c in password)): 38 | print_frame_info() 39 | return True 40 | else: 41 | print_frame_info() 42 | return False 43 | 44 | validate_email("pilmokim99@gmail.com") 45 | check_password_complexity("1234") 46 | ``` 47 | Screenshot 2024-05-13 at 8 36 10 PM 48 | -------------------------------------------------------------------------------- /8th_members/김원경/11주차.md: -------------------------------------------------------------------------------- 1 | # 원하는 Type 분석해보기: List 타입 2 | ### 1. data structure of python list 3 | ![enter image description here](https://miro.medium.com/max/720/1*OJr_4YC6OMB30XQzvPmPkw.png) 4 | ![enter image description here](https://devocean.sk.com/CKFinderJava/userfiles/images/py%EA%B5%AC%EC%A1%B0.png) 5 | ### Python list data structure 6 | ![enter image description here](https://miro.medium.com/max/720/1*l1O3TOk75WyRzrDn2bUe5A.png) 7 | - PyListObject: python list의 C 구현체. 8 | - PyObject_VAR_HEAD: 인스턴스마다 길이가 변하는 객체를 선언할 때 사용되는 macro. 9 | - **ob_item: 이중 포인터 (리스트 원소들의 포인터 배열에 대한 포인터). 객체 주소들을 저장한다. 10 | - allocated: 리스트에 할당된 크기 11 | - **Py__Object: 모든 클래스들의 조상인 PyObject를 상속받은 뒤 __에 type명(ex: int, var, list, array etc.)을 붙여 각 타입에 대한 파이썬 클래스를 구현. 12 | 13 | 이에 의해 파생되는 특징들? 14 | #### 1) 동적 타입 지원 15 | ![enter image description here](https://devocean.sk.com/CKFinderJava/userfiles/images/image%282671%29.png) 16 | 한 연산 수행 중간중간에 type checking이 많아 정적 배열보다 동작 느림 17 | 18 | #### 2) 크기가 가변적(동적) 19 | 처음에 크기를 작게 잡아뒀다 꽉 차면 list_resize 메서드를 작동시켜 크기를 늘려준다. (용어: 더블링) 20 | → 해당 작업 발생 시 정적 배열보다 동작 속도 느려짐 21 | 22 | #### 3) 포인터를 이중으로 거침 23 | ob_items**의 특징에 의해 value를 바로 얻을 수 없어 속도 느림 24 | 25 | #### 4) 캐시의 메모리 지역성 문제 26 | ![enter image description here](https://computerscience.chemeketa.edu/cs160Reader/_images/Memory-Hierarchy.jpg) 27 | ![enter image description here](https://devocean.sk.com/CKFinderJava/userfiles/images/image%282672%29.png) 28 | ![enter image description here](https://devocean.sk.com/CKFinderJava/userfiles/images/image%282673%29.png) 29 | list의 0, 1번 객체 즉 PyObject를 가리키는 포인터 주소는 메모리 상에서 인접하지만 value는 인접하지 않음 30 | → nparray와 비교하면, 캐싱 시 메모리 지역성 문제로 cache hit rate가 더 낮음 31 | -------------------------------------------------------------------------------- /8th_members/이용우/6주차.md: -------------------------------------------------------------------------------- 1 | ### 요약 2 | 3 | 코드 객체는 프레임 객체에 삽입된다. 4 | 파이썬 타입인 프레임 객체는 C와 파이썬 코드 양쪽에서 참조할 수 있다. 5 | 6 | 7 | 프레임 객체는 코드 객체의 명령을 실행하는 데 필요한 런타임 데이터를 포함한다. 8 | 런타임 데이터에는 지역, 전역 변수 및 내장 모듈 등이 포함된다. 9 | 10 | 11 |
12 | 13 | 14 | 코드 객체에서 PyEval_EvalCode → _PyFrame_New_NoTrack를 거쳐서 15 | 프레임 객체를 반환받게 된다. 그리고 프레임 객체는 다음과 같이 구성된다. 16 | 17 | 18 | 19 |


20 | 21 | 22 | ### TODO: 파이썬에서 프레임 객체 접근해보기 23 | 프레임 객체는 함수가 호출될 때마다 만들어집니다. 24 | 이를 파이썬의 inspect.currentframe() 메소드를 사용하여 접근할 수 있습니다. 25 | 26 | 다음은 현재 함수의 프레임 객체 상태를 확인할 수 있는 예제 코드이다. 27 | 28 |
29 | 30 | ``` python 31 | import dis 32 | import inspect 33 | 34 | global_variable01 = 'gvalue01' 35 | 36 | def print_frame_info(): 37 | frame = inspect.currentframe().f_back # 현재 함수의 호출자 프레임 38 | try: 39 | print("Function Name:", frame.f_code.co_name) 40 | print("File Name:", frame.f_code.co_filename) 41 | print("Line No:", frame.f_back.f_lineno) 42 | print("Local Variables:", list(frame.f_locals.keys())) 43 | print("Global Variables:", list(frame.f_globals.keys())) 44 | # dis.dis(frame.f_code) # 역 디스어셈블러 45 | print("\n\n") 46 | finally: 47 | del frame 48 | 49 | def sample01(): 50 | sample01_variable = 1 51 | print_frame_info() 52 | 53 | def sample02(): 54 | sample02_variable = 2 55 | print_frame_info() 56 | 57 | sample01() 58 | sample02() 59 | ``` 60 | 61 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /8th_members/전희선/10주차.md: -------------------------------------------------------------------------------- 1 | ### 멀티스레딩 + 스레드 개수 제한 통한 port scanner 실행 2 | 3 | - 실행 코드 4 | ```python 5 | import socket 6 | import time 7 | from concurrent.futures import ThreadPoolExecutor, as_completed 8 | from queue import Queue 9 | import sys 10 | 11 | timeout = 1.0 12 | 13 | def check_port(host: str, port: int) -> int: 14 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 15 | sock.settimeout(timeout) 16 | result = sock.connect_ex((host, port)) 17 | if result == 0: 18 | return port 19 | return None 20 | 21 | def main(): 22 | MAX_WORKERS = int(sys.argv[1]) # worker 수 입력으로 받아 다르게 테스트 23 | 24 | start = time.time() 25 | host = "localhost" # Replace with a host you own 26 | open_ports = [] 27 | 28 | with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: 29 | futures = [executor.submit(check_port, host, port) for port in range(10000, 65536)] # port 범위 확장 30 | 31 | for future in as_completed(futures): 32 | port = future.result() 33 | if port is not None: 34 | open_ports.append(port) 35 | 36 | for port in open_ports: 37 | print(f"Port {port} is open") 38 | print(f"Completed scan in {time.time() - start:.2f} seconds") 39 | 40 | if __name__ == '__main__': 41 | main() 42 | ``` 43 | - 결과: worker 수를 30으로 했을 때 가장 적게 걸리는 점을 통해, 멀티스레딩도 오버헤드가 존재하며 (멀티프로세스에 비해 상대적으로 적을 뿐) worker 개수가 많다고 항상 좋은 것은 아니라는 점을 확인할 수 있었습니다 :) 44 | image 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CPython-Guide jupyter-book 작업 가이드 2 | 3 | jupyter-book github page 접속 주소: https://pseudo-lab.github.io/CPython-Guide 4 | 5 | 1. 저장소를 fork 합니다. 6 | 7 | ``` 8 | Pseudo-Lab/CPython-Guide 9 | ``` 10 | 11 | 2. 저장소 및 python 패키지를 받습니다. 12 | 13 | ```bash 14 | git clone https://github.com/[작업자의 Github아이디]/CPython-Guide.git 15 | cd [CPython-Guide 폴더] # 윈도우즈 command line의 /d 옵션도 같이 16 | pip install -r requirements.txt # jupyter-book 패키지 설치, ghp-import는 꼭 설치안해도됨. (git action용) 17 | ``` 18 | 19 | 3. 담당 페이지 작업을 진행합니다. 20 | 그 후 빌드를 돌린 후 _build/html/index.html을 열어서 결과를 확인합니다. 21 | 22 | ```bash 23 | # 작업 root 경로 (working directory)가 CPython-Guide 최상위 경로인 경우. 24 | jupyter-book build ./book 25 | ``` 26 | 27 | 4. 정상적으로 완료되었다면 pull request를 날립니다. 28 | 29 | ```bash 30 | # TODO: pull request 하는 방법 첨부 예정. 31 | ``` 32 | 33 | 5. pull request 승인 후 push가 완료되면 자동으로 사이트가 빌드됩니다. 34 | 35 | 36 | 37 | # jupyter-book 작업 구조 38 | ```yaml 39 | CPython-Guide 40 | ├── .github # git action workflow가 있습니다. 41 | ├── book # 문서 메인 폴더 입니다. 42 | │ ├── docs # 문서가 모여있는 폴더입니다. 43 | │ ├── images # 문서에 들어가는 이미지 폴더입니다. 44 | │ ├── _config.yml # github page config 입니다. 45 | │ ├── _toc.yml # 문서 레이아웃 구성 파일 입니다. 46 | │ ├── intro.md # 문서의 시작 페이지 파일 입니다. 47 | ├── README.md 48 | ├── requirements.txt 49 | └── .gitignore 50 | ``` 51 | 문서는 book/docs 폴더에 추가하고 작성합니다. 52 | _toc.yml에 문서를 등록해야 페이지에 보입니다. 53 | 54 | # 파일명 규칙 55 | 1. docs: 챕터번호_섹션번호_문서제목 56 | (0_0_dev_env_setup.md, 0_1_directory_structure.md, 챕터 최상단은 0번 섹션으로 처리) 57 | 2. images: 챕터폴더/사진순서(두자리)_사진내용 58 | (0_dev_env_setup/00_vscode_plugin.png, 0_dev_env_setup/01_tasks_explorer_result.png) 59 | 60 | 61 | # 로컬에서 빌드한 페이지가 조금 이상할 때 62 | _build 폴더를 삭제 후 다시 빌드합니다. 이전 빌드 결과물에 대한 잔여물이 남는 케이스입니다. -------------------------------------------------------------------------------- /8th_members/이용우/4주차.md: -------------------------------------------------------------------------------- 1 | # 4주차 2 | ### 목차 3 | 1. [Lexer](#lexer) 4 | 2. [중요한 용어들](#중요한-용어들) 5 | 3. [미션](#미션) 6 | - [instaviz로 AST 시각화 해보기](#instaviz로-ast-시각화-해보기) 7 | - ["거의 같음" 연산자를 문법에 추가하고 AlE 타입의 객체를 출력해보기](#거의-같음-연산자를-문법에-추가하고-ale타입의-객체를-출력-해보기) 8 | 9 | 10 |


11 | 12 | 13 | ### Lexer 14 | Lexer는 Tokenizer로 쪼개진 토큰들의 의미를 분석하는 역할을 한다. 15 | Tokenizer를 거치며 의미있는 단위로 쪼개지고, 16 | Lexer를 거치며 그 의미를 분석하는 과정을 통틀어서 Lexical Analyze라고 한다. 17 | 18 | > 예를 들어 return 명령어를 분석해보자. 19 | > - return이라는 단어에서 r, e, t, u, r, n은 각각 따로 놓고 보면 아무 의미도 가지지 않는다. 20 | > - Tokenizer를 거치며 return이 의미 있는 단어가 된다. (Tokenizing) 21 | > - Lexer를 거치며 이 토큰은 무언가를 반환하는 명령어임을 인지하게 된다. 22 | > 23 | > 위 과정을 거치며 생성된 오브젝트 {type: 명령어, value: "return", child: []}가 Parser에 전달된다. 24 | 25 |
26 | 27 | - Tokenizer : 구문에서 의미 있는 요소들을 토큰으로 쪼깸 28 | - Lexer : 토큰의 의미를 분석 29 | - Parser : Lexical analyze된 후의 리턴값인 CST를 AST로 바꿔줌 30 | 31 | 32 |


33 | 34 | ### 중요한 용어들 35 | 36 | | 용어 | 설명 | 37 | |----------| -------------------------------------------------| 38 | |AST | 파이썬 문법과 문장들에 대한 문맥(Context) 있는 트리 표현 | 39 | |CST | 토큰과 심볼에 대한 문맥(Context)이 없는 트리 표현 | 40 | |Parse Tree | CST의 다른 이름 | 41 | |Token | 심볼의 종류 중 하나 | 42 | |Tokenizing | 텍스트를 토큰들로 변환하는 과정 | 43 | |Parsing | 텍스트를 CST나 AST로 변환하는 과정 | 44 | 45 |


46 | 47 | ### 미션 48 | #### instaviz로 AST 시각화 해보기 49 | 50 | image 51 | 52 | 53 |


54 | 55 | #### ‘거의 같음’ 연산자를 문법에 추가하고 AlE타입의 객체를 출력 해보기 56 | 57 | image 58 | 59 | -------------------------------------------------------------------------------- /8th_members/전희선/3주차.md: -------------------------------------------------------------------------------- 1 | 1. CPython 인터프리터 실행 과정 코드 레벨로 이해하기 2 |
image 3 |
image 4 |
image 5 |
image 6 |
image 7 |
image 8 | 2. 파이썬 세션에서 runtime flag 확인하기 9 | - 플래그 미사용 10 |
image 11 | - `-X dev` 플래그 사용 (`dev_mode=True`) 12 |
image 13 | - `-X dev -X utf8` 플래그 사용 (`dev_mode=True, utf8_mode=1`) 14 |
image 15 | - `-X dev -q` 플래그 사용 (`dev_mode=True, quiet=1` + python version 미출력) 16 |
image 17 | 3. importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기 18 |
image 19 | -------------------------------------------------------------------------------- /book/docs/0_0_dev_env_setup.md: -------------------------------------------------------------------------------- 1 | # CPython 개발 환경 세팅 2 | CPython-Guide는 CPython 파헤치기 책과 동일한 python3.9 버전을 기반으로 진행됩니다. 3 | 4 | ## CPython git 저장소 받기 5 | ```bash 6 | git clone --branch 3.9 https://github.com/python/cpython.git 7 | ``` 8 | 저장소를 받은 후 Visual Studio Code로 해당 폴더를 열어줍니다. 9 | 10 | ## Visual Studio Code 개발 환경 세팅 11 | ![VSCode 설치 플러그인](../images/0_dev_env_setup/00_vscode_plugin.png) 12 | 위 플러그인들을 설치합니다. 13 | 14 | ## task.json 작성 15 | ```json 16 | { 17 | "version": "2.0.0", 18 | "tasks": [ 19 | { 20 | "label": "build", 21 | "type": "shell", 22 | "group": { 23 | "kind": "build", 24 | "isDefault": true 25 | }, 26 | "windows": { 27 | "command": "PCBuild/build.bat", 28 | "args": ["-p", "x64", "-c", "Debug"] 29 | }, 30 | "linux": { 31 | "command": "make -j2 -s" 32 | }, 33 | "osx": { 34 | "command": "make -j2 -s" 35 | } 36 | } 37 | ] 38 | } 39 | ``` 40 | .vscode/task.json 파일을 생성하고 위 내용을 작성합니다. 41 | 42 | ![태스크 세팅 결과](../images/0_dev_env_setup/01_tasks_explorer_result.png) 43 | task.json 작성을 완료하면 TASK EXPLORER의 vscode 하위에 작성한 build task가 추가된 것을 볼 수 있습니다. 44 | 45 | ## launch.json 작성 46 | ```json 47 | { 48 | "version": "0.2.0", 49 | "configurations": [ 50 | { 51 | "name": "msvc cl.exe debug cpython", 52 | "type": "cppvsdbg", 53 | "request": "launch", 54 | "program": "PCBuild/amd64/python_d.exe", 55 | "args": [], 56 | "stopAtEntry": false, 57 | "cwd": "${workspaceFolder}", 58 | "environment": [], 59 | "externalConsole": true, 60 | "preLaunchTask": "build" 61 | } 62 | ] 63 | } 64 | ``` 65 | .vscode/launch.json 파일을 생성하고 위 내용을 작성합니다. 66 | 67 | 이제 F5를 누르면 CPython 빌드 진행 및 디버깅을 할 수 있습니다. 68 | CPython의 진입점이 되는 Programs/python.c의 9번 라인에 디버그 브레이크를 걸고 실행해봅니다. 69 | ![CPyhton 디버깅](../images/0_dev_env_setup/02_cpython_debugging.png) 70 | 위와 같이 디버깅 잡힌 것을 볼 수 있습니다. 71 | 72 | 개발환경 세팅은 여기까지입니다. 73 | 74 | -------------------------------------------------------------------------------- /8th_members/김진아/12주차.md: -------------------------------------------------------------------------------- 1 | # 12주차 2 | 3 | ## 나만의 Test Case 만들기 4 | 5 | ### 구조 6 | 7 | ``` 8 | . 9 | ├── tests 10 | │ └── test_normalize.py 11 | └── text_processing.py 12 | ``` 13 | 14 | ### `text_processing.py` 15 | 16 | ```python 17 | def normalize(input_str): 18 | out = input_str.lower() 19 | out = out.strip() 20 | while ' ' in out: 21 | out = out.replace(' ', ' ') 22 | return out 23 | ``` 24 | 25 | ### `test_normalize.py` 26 | 27 | ```python 28 | import unittest 29 | from text_processing import normalize 30 | 31 | 32 | class TestTextNormalize(unittest.TestCase): 33 | def test_normalize(self): 34 | test_str = "This is an example." 35 | pred = normalize(test_str) 36 | self.assertEqual(pred, "this is an example.") 37 | 38 | test_str = " EXTRA SPACE " 39 | pred = normalize(test_str) 40 | self.assertEqual(pred, "extra space") 41 | 42 | test_str = "THIS IS ALL CAPS!!" 43 | pred = normalize(test_str) 44 | self.assertEqual(pred, "this is all caps!!") 45 | 46 | test_str = " " 47 | pred = normalize(test_str) 48 | self.assertEqual(pred, "") 49 | 50 | test_str = "this is all lower space..." 51 | pred = normalize(test_str) 52 | self.assertEqual(pred, "this is all lower space...") 53 | 54 | test_str = " H e L l O !" 55 | pred = normalize(test_str) 56 | self.assertEqual(pred, "h e l l o !") 57 | 58 | test_str = "" 59 | pred = normalize(test_str) 60 | self.assertEqual(pred, "") 61 | 62 | test_str = "........" 63 | pred = normalize(test_str) 64 | self.assertEqual(pred, "........") 65 | 66 | test_str = "EX A M P LE" 67 | pred = normalize(test_str) 68 | self.assertEqual(pred, "ex a m p le") 69 | 70 | test_str = "AbCd EfGh IjKl MnOp" 71 | pred = normalize(test_str) 72 | self.assertEqual(pred, "abcd efgh ijkl mnop") 73 | ``` 74 | 75 | ### 결과 76 | 77 | 스크린샷 2024-06-30 오후 12 29 06 78 | -------------------------------------------------------------------------------- /8th_members/이용우/1주차.md: -------------------------------------------------------------------------------- 1 | # 1주차 2 | ### 목차 3 | 1. [CPython 소스코드 다운로드 및 환경 구성](#cpython-소스코드-다운로드-및-환경-구성) 4 | 1-1. [VSCode 코드 구성하기](#vscode-코드-구성하기) 5 | 1-2. [작업과 실행 파일 설정](#작업과-실행-파일-설정) 6 | 1-3. [환경 구성 켑처](#환경-구성-결과) 7 | 2. [스터디에서 이루고 싶은 목표 & 함께 하게 된 소감](#스터디에서-이루고-싶은-목표--함께-하게-된-소감) 8 | 9 |

10 | 11 | ## CPython 소스코드 다운로드 및 환경 구성 12 | ### VSCode 코드 구성하기 13 | VSCode는 온라인 플러그인 마켓 플레이스를 제공하는 확장 가능한 코드 편집기이다. 14 | 통합 git 인터페이스를 제공하며, C와 파이썬 모두를 지원하기 때문에 CPython을 위한 좋은 선택이 될 수 있다. 15 | 16 | Extensions 패널에 접근하여 `ms-vscode.cpptools`와 같은 고유 식별자로 확장을 검색할 수 있다. 17 | C/C++ for Visual Studio Code를 클릭하여 다운로드하도록 하자. 18 | 19 | 20 | 또한 권장되는 확장은 아래와 같다. 21 | |Extension|Description| 22 | |--|--| 23 | |C/C++ (`ms-vscode.cpptools`)|인텔리센스, 디버깅, 코드 강조 등의 C/C++ 지원을 제공| 24 | |Python (`ms-python.python`)|파이썬 코드 편집, 디버깅, 탐색 등의 파이썬 지원을 제공| 25 | |reStructuredText (`lextudio.restructuredtext`)|CPython 문서에 사용되는 reStructuredtext에 대한 지원을 제공| 26 | |Task Explorer (`spmeesseman.vscode-taskexplorer`)|make 작업을 편리하게 실행할 수 있는 Task Explorer 패널을 Explorer 탭 안에 추가| 27 | 28 | 29 |

30 | 31 | ### 작업과 실행 파일 설정 32 | VSCode는 작업 디렉터리 내부의 `.vscode` 폴더를 작업 공간 설정에 사용한다. 33 | 폴더가 없으면 새로 만들고 다음 파일들을 추가해서 작업 공간을 설정할 수 있다. 34 | 35 | - 프로젝트 실행 명령에 대한 `tasks.json` 36 | - 디버거를 위한 `launch.json` 37 | - 기타 플러그인을 위한 파일 38 | 39 | `tasks.json` 파일에 작업을 등록할 수 있다. 40 | 41 | ```json 42 | { 43 | "version": "2.0.0", 44 | "tasks": [ 45 | { 46 | "label": "build", 47 | "type": "shell", 48 | "group": { 49 | "kind": "build", 50 | "isDefault": true 51 | }, 52 | "windows": { 53 | "command": "PCBuild/build.bat", 54 | "args": ["-p", "x64", "-c", "Debug"] 55 | }, 56 | "linux": { 57 | "command": "make -j2 -s" 58 | }, 59 | "osx": { 60 | "command": "make -j2 -s" 61 | } 62 | } 63 | ] 64 | } 65 | ``` 66 | 67 |

68 | 69 | ### 환경 구성 결과 70 | 71 | 72 | 73 | 74 |


75 | 76 | ## 스터디에서 이루고 싶은 목표 & 함께 하게 된 소감 77 | 이번 스터디를 통해 Python 언어를 더 깊이 있게 이해하고, 78 | 이 스터디를 마친 후에는 Python을 원하는 기능 및 스펙에 맞게 79 | 입맛대로 커스텀 할 수 있는 엔지니어로 성장하기 위한 초석을 다지고 싶습니다. 80 | 81 | 이번 CPython 스터디에 참여하여 관심사가 비슷한 분들과 함께 할 수 있게 되어 기쁘게 생각하고 있습니다. 82 | 모든 분들이 이번 스터디를 통해 각자 성취, 혹은 원하는 바를 이룰 수 있었으면 좋겠습니다. 83 | 앞으로 스터디 기간 동안 잘 부탁드립니다. 감사합니다🙂 -------------------------------------------------------------------------------- /8th_members/이용우/9주차.md: -------------------------------------------------------------------------------- 1 | ### 멀티 프로세싱 요약 2 | **장점** 3 | `multiprocessing`은 확장 가능한 파이썬용 병렬 실행 API를 제공한다. 4 | 프로세스 간 데이터 공유가 가능하며, CPU 집약적인 작업을 병렬로 쪼개서 5 | 멀티코어 또는 멀티 CPU 컴퓨터의 장점을 활용할 수도 있다. 6 | 7 | **단점** 8 | 단, I/O 집약적인 작업의 경우에는 멀티 프로세싱이 적합하지 않다. 9 | 예를 들어 Worker 프로세스 4개를 Spawn 하고 같은 파일을 읽고 쓰는 경우, 10 | 한 프로세스가 작업하는 동안 나머지 프로세스 3개는 Lock 해제될 때 까지 기다려야 한다. 11 | 12 | 멀티프로세싱은 새로운 파이썬 인터프리터를 시작하는 데 필요한 시간과 처리 오버헤드로 인해 13 | 시간 소요가 얼마 되지 않는 작업에는 적합하지 않다. 14 | 15 |
16 | 17 | → I/O 작업과 시간 소요가 얼마되지 않는 작업에 대해서는 멀티 쓰레딩 방식이 더 적합하다. 18 | 19 |

20 | 21 | 22 | ### CPU Bound, Unbound 예제 실행 23 | #### CPU Bound 24 | 25 | ``` python 26 | import time 27 | from typing import List 28 | 29 | def compute_squares(numbers: List[int]) -> List[int]: 30 | return [x**2 for x in numbers] 31 | 32 | 33 | def no_multiprocessing(): 34 | numbers = range(1, 10000000) 35 | start_time = time.time() 36 | results = compute_squares(numbers) 37 | end_time = time.time() 38 | 39 | print(f"Duration without multiprocessing: {end_time - start_time} seconds") 40 | 41 | if __name__ == '__main__': 42 | no_multiprocessing() 43 | ``` 44 | 45 | 46 | 47 | 48 |
49 | 50 | #### CPU Unbound 51 | 52 | ``` python 53 | import time 54 | import multiprocessing as mp 55 | from typing import List 56 | 57 | def compute_squares(numbers: List[int]) -> List[int]: 58 | return [x**2 for x in numbers] 59 | 60 | 61 | def multiprocessing_compute(): 62 | numbers = range(1, 10000000) 63 | process_cnt = mp.cpu_count() 64 | print(f"cpu count: {process_cnt}") 65 | 66 | pool = mp.Pool(process_cnt) 67 | 68 | # 데이터 분할 69 | size = len(numbers) // process_cnt 70 | numbers_split = [ 71 | numbers[i * size:(i + 1) * size] 72 | for i in range(process_cnt) 73 | ] 74 | 75 | start_time = time.time() 76 | results = pool.map(compute_squares, numbers_split) 77 | end_time = time.time() 78 | 79 | pool.close() 80 | pool.join() 81 | print(f"Duration with multiprocessing: {end_time - start_time} seconds") 82 | 83 | 84 | if __name__ == '__main__': 85 | multiprocessing_compute() 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /8th_members/전희선/12주차.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ✗ tree tests 3 | tests 4 | ├── __init__.py 5 | ├── test_normalize.py 6 | └── text_processing.py 7 | ``` 8 | - text_processing.py 9 | ```python 10 | def normalize(input_str): 11 | """ 12 | 인풋으로 받는 스트링에서 아래의 규칙으로 정규화된 스트링을 반환하는 함수입니다. 13 | * 모든 단어들은 소문자로 변환됨 14 | * 띄어쓰기는 한칸으로 되도록 함 15 | * 앞뒤 필요없는 띄어쓰기는 제거함 16 | Parameters: 17 | input_str (string): 영어로 된 대문자, 소문자, 띄어쓰기, 문장부호, 숫자로 이루어진 string 18 | ex - " EXTRA SPACE " 19 | Returns: 20 | normalized_string (string): 정규회된 string 21 | ex - 'extra space' 22 | Examples: 23 | >>> import text_processing as tp 24 | >>> example = " EXTRA SPACE " 25 | >>> tp.normalize(example) 26 | 'extra space' 27 | """ 28 | out = input_str.lower() 29 | out = out.strip() 30 | while ' ' in out: 31 | out = out.replace(' ', ' ') 32 | return out 33 | ``` 34 | - test_normalize.py 35 | ```python 36 | import unittest 37 | from text_processing import normalize 38 | 39 | 40 | class TestTextNormalize(unittest.TestCase): 41 | def test_normalize(self): 42 | test_str = "This is an example." 43 | pred = normalize(test_str) 44 | self.assertEqual(pred, "this is an example.") 45 | 46 | def test_extra_space(self): 47 | test_str = " EXTRA SPACE " 48 | pred = normalize(test_str) 49 | self.assertEqual(pred, "extra space") 50 | 51 | def test_uppercase(self): 52 | test_str = "THIS IS ALL UPPERCASE!!" 53 | pred = normalize(test_str) 54 | self.assertEqual(pred, "this is all uppercase!!") 55 | 56 | def test_lowercase(self): 57 | test_str = "this is all lowercase..." 58 | pred = normalize(test_str) 59 | self.assertEqual(pred, "this is all lowercase...") 60 | 61 | def test_whitespace(self): 62 | test_str = " " 63 | pred = normalize(test_str) 64 | self.assertEqual(pred, "") 65 | ``` 66 | ### Result 67 | image 68 | -------------------------------------------------------------------------------- /8th_members/이성범/12주차.md: -------------------------------------------------------------------------------- 1 | # 12주차 2 | 3 | ## unittest 사용해보기 4 | ```python 5 | import unittest 6 | 7 | def normalize(input_str): 8 | """ 9 | 인풋으로 받는 스트링에서 아래의 규칙으로 정규화된 스트링을 반환하는 함수입니다. 10 | * 모든 단어들은 소문자로 변환됨 11 | * 띄어쓰기는 한칸으로 되도록 함 12 | * 앞뒤 필요없는 띄어쓰기는 제거함 13 | Parameters: 14 | input_str (string): 영어로 된 대문자, 소문자, 띄어쓰기, 문장부호, 숫자로 이루어진 string 15 | ex - " EXTRA SPACE " 16 | Returns: 17 | normalized_string (string): 정규회된 string 18 | ex - 'extra space' 19 | Examples: 20 | >>> import text_processing as tp 21 | >>> example = " EXTRA SPACE " 22 | >>> tp.normalize(example) 23 | 'extra space' 24 | """ 25 | out = input_str.lower() 26 | out = out.strip() 27 | while ' ' in out: 28 | out = out.replace(' ', ' ') 29 | return out 30 | 31 | class TestTextNormalize(unittest.TestCase): 32 | def test_normalize(self): 33 | test_str = "This is an example." 34 | pred = normalize(test_str) 35 | self.assertEqual(pred, "this is an example.") 36 | 37 | test_str = " EXTRA SPACE " 38 | pred = normalize(test_str) 39 | self.assertEqual(pred, "extra space") 40 | 41 | test_str = "THIS IS ALL CAPS!!" 42 | pred = normalize(test_str) 43 | self.assertEqual(pred, "this is all caps!!") 44 | 45 | test_str = " " 46 | pred = normalize(test_str) 47 | self.assertEqual(pred, "") 48 | 49 | test_str = "this is all lower space..." 50 | pred = normalize(test_str) 51 | self.assertEqual(pred, "this is all lower space...") 52 | 53 | test_str = " H e L l O !" 54 | pred = normalize(test_str) 55 | self.assertEqual(pred, "h e l l o !") 56 | 57 | test_str = "" 58 | pred = normalize(test_str) 59 | self.assertEqual(pred, "") 60 | 61 | test_str = "........" 62 | pred = normalize(test_str) 63 | self.assertEqual(pred, "........") 64 | 65 | test_str = "EX A M P LE" 66 | pred = normalize(test_str) 67 | self.assertEqual(pred, "ex a m p le") 68 | 69 | test_str = "AbCd EfGh IjKl MnOp" 70 | pred = normalize(test_str) 71 | self.assertEqual(pred, "abcd efgh ijkl mnop") 72 | ``` 73 |

-------------------------------------------------------------------------------- /8th_members/이용우/2주차.md: -------------------------------------------------------------------------------- 1 | # 2주차 2 | ### 목차 3 | 1. [macOS에서 CPython 컴파일하기](#macos에서-cpython-컴파일하기) 4 | 2. [문법 다시 생성하기 (pass 키워드 변경해보기) 부분 원하는 키워드 다른걸로 바꿔보기 (결과 화면 캡쳐)](#문법-다시-생성하기-pass-키워드-변경해보기-부분-원하는-키워드-다른걸로-바꿔보기-결과-화면-캡쳐) 5 | 6 |

7 | 8 | ### macOS에서 CPython 컴파일하기 9 | macOS에서 CPython을 컴파일하려면 어플리케이션과 라이브러리가 추가로 필요하다. 10 | 그 중 Command Line Tools는 필수적인 C 컴파일러 툴킷으로 11 | 터미널로 설치하고 앱스토어에서 업데이트 할 수 있다. 12 | 13 | 다음 명령을 실행해 C 컴파일러 툴킷을 설치하면 14 | git, make, GNU C 컴파일러 등의 도구들이 설치된다. 15 | 16 | ``` 17 | $ xcode-select --install 18 | ``` 19 | 20 | 21 | 22 |

23 | 24 | PyPI에서 패키지를 받아 설치하려면 OpenSSL도 필요하다. 25 | HomeBrew로 macOS에 간단하게 OpenSSL을 설치할 수 있다. 26 | 27 | brew install 명령으로 CPython에 필요한 의존성을 설치하자. 28 | 29 | ``` 30 | $ brew install openssl xz zlib gdbm sqlite 31 | ``` 32 | 33 |

34 | 35 | zlib이 설치된 위치를 지정하고 구성 작업을 실행하자. 36 | 이 작업은 한 번만 실행하면 된다. 37 | 38 | ``` 39 | # cd ~/your/cpython/path 40 | 41 | $ CPPFLAGS="-I$(brew --prefix zlib)/include" \ 42 | LDFLAGS="-L$(brew --prefix zlib)/lib" \ 43 | ./configure --with-openssl=$(brew --prefix openssl) \ 44 | --with-pydebug 45 | ``` 46 | 47 |

48 | 49 | ./configure가 저장소 최상단에 위치한 Makefile이 빌드 과정을 자동화한다. 50 | 다음 명령어로 CPython 바이너리를 빌드하자. 51 | 52 | ``` 53 | $ make -j2 -s 54 | ``` 55 | 56 |


57 | 58 | ### 문법 다시 생성하기 (pass 키워드 변경해보기) 부분 원하는 키워드 다른걸로 바꿔보기 (결과 화면 캡쳐) 59 | CPython3.9 부터 도입된 새로운 PEG 생성기인 pegen을 테스트해 보기 위해 문법 일부를 변경해보자. 60 | Grammar → python.gram에서 간단한 정의인 small_stmt를 찾아 수정해보자. 61 | ※ small_stmt: 단일 독립 실행 가능한 구성요소 62 | 63 | ``` 64 | small_stmt[stmt_ty] (memo): 65 | | assignment 66 | | e=star_expressions { _Py_Expr(e, EXTRA) } 67 | | &'return' return_stmt 68 | | &('import' | 'from') import_stmt 69 | | &'raise' raise_stmt 70 | | 'pass' { _Py_Pass(EXTRA) } 71 | | &'del' del_stmt 72 | | &'yield' yield_stmt 73 | | &'assert' assert_stmt 74 | | ('break' | 'heartbreaker') { _Py_Break(EXTRA) } 75 | | 'continue' { _Py_Continue(EXTRA) } 76 | | &'global' global_stmt 77 | | &'nonlocal' nonlocal_stmt 78 | ``` 79 | 80 |

81 | 82 | CPython의 자동 문법 재생성 스크립트를 사용해 문법 파일을 다시 빌드하자. 83 | ``` 84 | $ make regen-pegen 85 | ``` 86 | 87 |

88 | 89 | CPython을 새 파서 테이블과 같이 컴파일하면 새 문법이 추가된다. 90 | 이전 장에서 소개한 운영 체제 별 컴파일 방법을 그대로 실행하면 된다. 91 | 92 | ``` 93 | $ make -j2 -s 94 | ``` 95 | 96 |

97 | 98 | -------------------------------------------------------------------------------- /8th_members/이용우/12주차.md: -------------------------------------------------------------------------------- 1 | ### Test Case 만들기 2 | ``` 3 | Project 4 | |- tests 5 | |- __init__.py 6 | |- test_normalize.py 7 | |- text_processing.py 8 | ``` 9 | 10 | 11 |

12 | 13 | ``` python 14 | def normalize(input_str): 15 | out = input_str.lower() 16 | out = out.strip() 17 | while ' ' in out: 18 | out = out.replace(' ', ' ') 19 | return out 20 | ``` 21 | 22 |
23 | 24 | ``` python 25 | import unittest 26 | from text_processing import normalize 27 | 28 | 29 | class TestTextNormalize(unittest.TestCase): 30 | def test_normalize(self): 31 | test_str = "This is an example." 32 | pred = normalize(test_str) 33 | self.assertEqual(pred, "this is an example.") 34 | 35 | test_str = " EXTRA SPACE " 36 | pred = normalize(test_str) 37 | self.assertEqual(pred, "extra space") 38 | 39 | test_str = "THIS IS ALL CAPS!!" 40 | pred = normalize(test_str) 41 | self.assertEqual(pred, "this is all caps!!") 42 | 43 | test_str = " " 44 | pred = normalize(test_str) 45 | self.assertEqual(pred, "") 46 | 47 | test_str = "this is all lower space..." 48 | pred = normalize(test_str) 49 | self.assertEqual(pred, "this is all lower space...") 50 | 51 | test_str = " H e L l O !" 52 | pred = normalize(test_str) 53 | self.assertEqual(pred, "h e l l o !") 54 | 55 | test_str = "" 56 | pred = normalize(test_str) 57 | self.assertEqual(pred, "") 58 | 59 | test_str = "........" 60 | pred = normalize(test_str) 61 | self.assertEqual(pred, "........") 62 | 63 | test_str = "EX A M P LE" 64 | pred = normalize(test_str) 65 | self.assertEqual(pred, "ex a m p le") 66 | 67 | test_str = "AbCd EfGh IjKl MnOp" 68 | pred = normalize(test_str) 69 | self.assertEqual(pred, "abcd efgh ijkl mnop") 70 | ``` 71 | 72 | 73 |

74 | 75 | 76 | ``` 77 | # tests 디렉토리 내 모든 테스트 파일 실행 78 | $ python -m unittest discover tests -v 79 | ``` 80 | 81 | ``` 82 | # 특정 테스트 파일 실행 83 | $ python -m unittest tests.test_normalize -v 84 | ``` 85 | 86 | ``` 87 | # 특정 테스트 스위트 실행 88 | $ python -m unittest tests.test_normalize.TestTextNormalize 89 | ``` 90 | 91 | ``` 92 | # 특정 테스트 케이스 실행 93 | $ python -m unittest tests.test_normalize.TestTextNormalize.test_normalize 94 | ``` 95 | 96 | 97 | -------------------------------------------------------------------------------- /book/docs/2_0_settings.md: -------------------------------------------------------------------------------- 1 | # 2. 개발 환경 세팅 2 | 3 | CPython-Guide는 CPython 파헤치기 책과 동일한 Python 3.9 버전을 기반으로 진행됩니다. 4 | 5 | ## Visual Studio Code 개발 환경 세팅 6 | 7 | ### 플러그인 설치 8 | 아래와 같은 플러그인들을 설치해줍니다. 9 | ![VSCode 설치 플러그인](../images/2_settings/00_vscode_plugin.png) 10 | 11 | ### .vscode/task.json 작성 12 | 프로젝트 실행 명령에 대한 json 파일 `.vscode/task.json`을 아래와 같이 생성해줍니다. 13 | 14 | ```json 15 | { 16 | "version": "2.0.0", 17 | "tasks": [ 18 | { 19 | "label": "build", 20 | "type": "shell", 21 | "group": { 22 | "kind": "build", 23 | "isDefault": true 24 | }, 25 | "windows": { 26 | "command": "PCBuild/build.bat", 27 | "args": ["-p", "x64", "-c", "Debug"] 28 | }, 29 | "linux": { 30 | "command": "make -j2 -s" 31 | }, 32 | "osx": { 33 | "command": "make -j2 -s" 34 | } 35 | } 36 | ] 37 | } 38 | ``` 39 | 40 | 위와 같이 파일 작성을 완료하면 TASK EXPLORER의 vscode 하위에 작성한 build task가 추가된 것을 볼 수 있습니다. 41 | ![태스크 세팅 결과](../images/2_settings/01_tasks_explorer_result.png) 42 | 43 | 44 | ### .vscode/launch.json 작성 45 | 디버거를 위한 json 파일 `.vscode/launch.json`을 아래와 같이 생성해줍니다. 46 | 47 | - macOS 48 | ```json 49 | { 50 | "version": "0.2.0", 51 | "configurations": [ 52 | { 53 | "name": "Debug C Code", 54 | "type": "cppdbg", 55 | "request": "launch", 56 | "program": "${workspaceFolder}/python.exe", 57 | "args": [], 58 | "stopAtEntry": false, 59 | "cwd": "${workspaceFolder}", 60 | "environment": [], 61 | "externalConsole": true, 62 | "MIMode": "lldb" 63 | } 64 | ] 65 | } 66 | ``` 67 | - Windows 68 | ```json 69 | { 70 | "version": "0.2.0", 71 | "configurations": [ 72 | { 73 | "name": "msvc cl.exe debug cpython", 74 | "type": "cppvsdbg", 75 | "request": "launch", 76 | "program": "PCBuild/amd64/python_d.exe", 77 | "args": [], 78 | "stopAtEntry": false, 79 | "cwd": "${workspaceFolder}", 80 | "environment": [], 81 | "externalConsole": true, 82 | "preLaunchTask": "build" 83 | } 84 | ] 85 | } 86 | ``` 87 | 88 | 이제 F5를 누르면 CPython 빌드 진행 및 디버깅을 할 수 있습니다. 89 | CPython의 진입점이 되는 Programs/python.c의 9번 라인에 디버그 브레이크를 걸고 실행해보면, 90 | 아래와 같이 디버깅이 잡힌 것을 확인할 수 있습니다. 91 | ![CPyhton 디버깅](../images/2_settings/02_cpython_debugging.png) 92 | -------------------------------------------------------------------------------- /book/docs/1_0_welcome_to_cpython.md: -------------------------------------------------------------------------------- 1 | # 1. CPython 살펴보기 2 | 3 | > 앞으로 저희는 CPython에 대해 아래 내용을 다루게 됩니다 🚀 4 | > - **CPython 소스 코드 읽고 탐색 / 컴파일**하기 5 | > - Python 문법 수정하고 컴파일해서 자신만의 CPython 버전 만들기 6 | > - list, dictionary, generator 등의 **내부 작동 방식 이해**하기 7 | > - CPython **메모리 관리 기능** 이해하기 8 | > - **병렬성과 동시성**을 통해 Python 코드 확장하기 9 | > - 코어 타입에 새로운 기능 추가하기 10 | > - **테스트 스위트** 실행하기 11 | > - Python **코드와 런타임 성능을 프로파일하고 벤치마크**하기 12 | > - C 코드와 Python 코드를 전문가처럼 **디버깅**하기 13 | > - CPython 라이브러리의 구성 요소를 수정하거나 개선해서 **향후 CPython에 기여**하기 14 | 15 | ## 1.1 CPython이란? 16 | 17 | - Python 구현체 중 하나로, 일반적으로 이용하는 [python.org](http://python.org) 에서 제공하는 공식 파이썬 구현체입니다. 18 | - 이름에서 알 수 있듯이, CPython은 C로 구현되어 있습니다. 19 | - 다른 python 구현체 20 | - Jython 21 | - Java로 작성된 파이썬 구현체 22 | - JVM(Java Virtual Machine)에서 실행 23 | - IronPython 24 | - C#로 작성된 파이썬 구현체 25 | - .NET 프레임워크 사용 26 | - PyPy 27 | - Python 정적 타입으로 작성된 파이썬 구현체 28 |
(정적 타입: 실행하기 전에 변수의 type을 미리 결정하고, 그 이후에는 type을 변경하지 않는 방식) 29 | - JIT(Just-In-Time: 프로그램을 실행하는 동안 실시간으로 기계어로 변환) 컴파일러 방식으로 구현되어 기존 interpreter 방식보다 빠르고 효율적 30 | 31 | ## 1.2 CPython 배포판 구성 요소 32 | 33 | - **언어 사양(Language Specification)**: 파이썬 언어의 문법, 구문, 의미론 34 | - ex) `[]`: 인덱싱, 슬라이싱, 빈 리스트 생성을 위해 사용 35 | - **컴파일러(Interpreter)**: C 언어로 작성된 컴파일러 36 | - 파이썬 소스 코드 → 실행 가능한 기계어로 변환하는 역할 37 | - **표준 라이브러리 모듈(Standard Library Modules)**: 기본적으로 포함되어 있는 패키지 38 | - ex) 파일 입출력, 네트워킹, 문자열 처리, 데이터 구조, GUI 프로그래밍 등 39 | - **코어 타입(Core Types)**: 내장 데이터 type 40 | - ex) 숫자, 문자열, list, tuple, dictionary 41 | - **테스트 스위트(Test Suite)**: 개발 및 유지 보수에 사용되는 테스트 모음 42 | - ex) 유닛 테스트, 통합 테스트, 성능 테스트 43 | 44 | ## 1.3 소스 코드 들여다보기 45 | 46 | - 소스 코드 다운로드 (3.9 버전을 기준으로 살펴볼 예정입니다.) 47 | ```bash 48 | git clone --branch 3.9 https://github.com/python/cpython 49 | ``` 50 | - 소스 코드 구성 51 | ```bash 52 | cpython 53 | ├── CODE_OF_CONDUCT.md 54 | ├── Doc # 문서 소스 파일 55 | ├── Grammar # 컴퓨터가 읽을 수 있는 언어 정의 56 | ├── Include # C 헤더 파일 57 | ├── LICENSE 58 | ├── Lib # 파이썬으로 작성된 표준 라이브러리 모듈 59 | ├── Mac # macOS를 위한 파일 60 | ├── Makefile.pre.in 61 | ├── Misc # 기타 파일 62 | ├── Modules # C로 작성된 표준 라이브러리 모듈 63 | ├── Objects # 코어 타입과 객체 모델 64 | ├── PC # 이전 버전의 윈도우를 위한 윈도우 빌드 지원 파일 65 | ├── PCbuild # 윈도우 빌드 지원 파일 66 | ├── Parser # 파이썬 파서 소스 코드 67 | ├── Programs # python 실행 파일과 기타 바이너리를 위한 소스 코드 68 | ├── Python # CPython 인터프리터 소스 코드 69 | ├── README.rst 70 | ├── Tools # CPython 빌드하거나 확장하는 데 유용한 독립 실행형 도구 71 | ├── aclocal.m4 72 | ├── config.guess 73 | ├── config.sub 74 | ├── configure 75 | ├── configure.ac 76 | ├── install-sh 77 | ├── pyconfig.h.in 78 | └── setup.py 79 | ``` 80 | -------------------------------------------------------------------------------- /8th_members/김필모/11주차.md: -------------------------------------------------------------------------------- 1 | 2 | # dictionay 타입에 대해서 알아보자 3 | ### dict get 4 | 5 | ```c 6 | static inline Py_ssize_t 7 | dictkeys_get_index(const PyDictKeysObject *keys, Py_ssize_t i) 8 | { 9 | Py_ssize_t s = DK_SIZE(keys); 10 | Py_ssize_t ix; 11 | 12 | if (s <= 0xff) { 13 | const int8_t *indices = (const int8_t*)(keys->dk_indices); 14 | ix = indices[i]; 15 | } 16 | else if (s <= 0xffff) { 17 | const int16_t *indices = (const int16_t*)(keys->dk_indices); 18 | ix = indices[i]; 19 | } 20 | #if SIZEOF_VOID_P > 4 21 | else if (s > 0xffffffff) { 22 | const int64_t *indices = (const int64_t*)(keys->dk_indices); 23 | ix = indices[i]; 24 | } 25 | #endif 26 | else { 27 | const int32_t *indices = (const int32_t*)(keys->dk_indices); 28 | ix = indices[i]; 29 | } 30 | assert(ix >= DKIX_DUMMY); 31 | return ix; 32 | } 33 | ``` 34 | 35 | ### dict set 36 | ```c 37 | static inline void 38 | dictkeys_set_index(PyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix) 39 | { 40 | Py_ssize_t s = DK_SIZE(keys); 41 | 42 | assert(ix >= DKIX_DUMMY); 43 | 44 | if (s <= 0xff) { 45 | int8_t *indices = (int8_t*)(keys->dk_indices); 46 | assert(ix <= 0x7f); 47 | indices[i] = (char)ix; 48 | } 49 | else if (s <= 0xffff) { 50 | int16_t *indices = (int16_t*)(keys->dk_indices); 51 | assert(ix <= 0x7fff); 52 | indices[i] = (int16_t)ix; 53 | } 54 | #if SIZEOF_VOID_P > 4 55 | else if (s > 0xffffffff) { 56 | int64_t *indices = (int64_t*)(keys->dk_indices); 57 | indices[i] = ix; 58 | } 59 | #endif 60 | else { 61 | int32_t *indices = (int32_t*)(keys->dk_indices); 62 | assert(ix <= 0x7fffffff); 63 | indices[i] = (int32_t)ix; 64 | } 65 | } 66 | ``` 67 | 68 | ### dict new 69 | ```c 70 | static PyObject * 71 | new_dict(PyDictKeysObject *keys, PyObject **values) 72 | { 73 | PyDictObject *mp; 74 | assert(keys != NULL); 75 | #if PyDict_MAXFREELIST > 0 76 | if (numfree) { 77 | mp = free_list[--numfree]; 78 | assert (mp != NULL); 79 | assert (Py_IS_TYPE(mp, &PyDict_Type)); 80 | _Py_NewReference((PyObject *)mp); 81 | } 82 | else 83 | #endif 84 | { 85 | mp = PyObject_GC_New(PyDictObject, &PyDict_Type); 86 | if (mp == NULL) { 87 | dictkeys_decref(keys); 88 | if (values != empty_values) { 89 | free_values(values); 90 | } 91 | return NULL; 92 | } 93 | } 94 | mp->ma_keys = keys; 95 | mp->ma_values = values; 96 | mp->ma_used = 0; 97 | mp->ma_version_tag = DICT_NEXT_VERSION(); 98 | ASSERT_CONSISTENT(mp); 99 | return (PyObject *)mp; 100 | } 101 | ``` 102 | 103 | -------------------------------------------------------------------------------- /8th_members/이성범/11주차.md: -------------------------------------------------------------------------------- 1 | # 11주차 2 | ## str type 분석 3 | ```c 4 | Objects/object.c 5 | 6 | INIT_TYPE(&PyUnicode_Type, "str"); 7 | ``` 8 | - python의 str은 PyUnicode_Type 을 서용함 9 | 10 | ```c 11 | Objects\unicodeobject.c 12 | 13 | PyTypeObject PyUnicode_Type = { 14 | PyVarObject_HEAD_INIT(&PyType_Type, 0) 15 | "str", /* tp_name */ 16 | sizeof(PyUnicodeObject), /* tp_basicsize */ 17 | 0, /* tp_itemsize */ 18 | /* Slots */ 19 | (destructor)unicode_dealloc, /* tp_dealloc */ 20 | 0, /* tp_vectorcall_offset */ 21 | 0, /* tp_getattr */ 22 | 0, /* tp_setattr */ 23 | 0, /* tp_as_async */ 24 | unicode_repr, /* tp_repr */ 25 | &unicode_as_number, /* tp_as_number */ 26 | &unicode_as_sequence, /* tp_as_sequence */ 27 | &unicode_as_mapping, /* tp_as_mapping */ 28 | (hashfunc) unicode_hash, /* tp_hash*/ 29 | 0, /* tp_call*/ 30 | (reprfunc) unicode_str, /* tp_str */ 31 | PyObject_GenericGetAttr, /* tp_getattro */ 32 | 0, /* tp_setattro */ 33 | 0, /* tp_as_buffer */ 34 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | 35 | Py_TPFLAGS_UNICODE_SUBCLASS, /* tp_flags */ 36 | unicode_doc, /* tp_doc */ 37 | 0, /* tp_traverse */ 38 | 0, /* tp_clear */ 39 | PyUnicode_RichCompare, /* tp_richcompare */ 40 | 0, /* tp_weaklistoffset */ 41 | unicode_iter, /* tp_iter */ 42 | 0, /* tp_iternext */ 43 | unicode_methods, /* tp_methods */ 44 | 0, /* tp_members */ 45 | 0, /* tp_getset */ 46 | &PyBaseObject_Type, /* tp_base */ 47 | 0, /* tp_dict */ 48 | 0, /* tp_descr_get */ 49 | 0, /* tp_descr_set */ 50 | 0, /* tp_dictoffset */ 51 | 0, /* tp_init */ 52 | 0, /* tp_alloc */ 53 | unicode_new, /* tp_new */ 54 | PyObject_Del, /* tp_free */ 55 | }; 56 | ``` 57 | - type 정의 58 | 59 | ```c 60 | /* Strings allocated through PyUnicode_FromUnicode(NULL, len) use the 61 | PyUnicodeObject structure. The actual string data is initially in the wstr 62 | block, and copied into the data block using _PyUnicode_Ready. */ 63 | typedef struct { 64 | PyCompactUnicodeObject _base; 65 | union { 66 | void *any; 67 | Py_UCS1 *latin1; 68 | Py_UCS2 *ucs2; 69 | Py_UCS4 *ucs4; 70 | } data; /* Canonical, smallest-form Unicode buffer */ 71 | } PyUnicodeObject; 72 | 73 | ``` 74 | - 구조체 -------------------------------------------------------------------------------- /book/images/4_grammar/00_train_diagram.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | foo 24 | 25 | 26 | 27 | 28 | 29 | 30 | bar 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | foo 54 | 55 | 56 | 57 | 58 | 59 | 60 | bar 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 112 | -------------------------------------------------------------------------------- /8th_members/고동희/11주차.md: -------------------------------------------------------------------------------- 1 | # 11주차 2 | 3 | ## Set 내부 구조 살펴보기 4 | ``` 5 | PyTypeObject PySet_Type = { 6 | PyVarObject_HEAD_INIT(&PyType_Type, 0) 7 | "set", /* tp_name */ 8 | sizeof(PySetObject), /* tp_basicsize */ 9 | 0, /* tp_itemsize */ 10 | /* methods */ 11 | (destructor)set_dealloc, /* tp_dealloc */ 12 | 0, /* tp_vectorcall_offset */ 13 | 0, /* tp_getattr */ 14 | 0, /* tp_setattr */ 15 | 0, /* tp_as_async */ 16 | (reprfunc)set_repr, /* tp_repr */ 17 | &set_as_number, /* tp_as_number */ 18 | &set_as_sequence, /* tp_as_sequence */ 19 | 0, /* tp_as_mapping */ 20 | PyObject_HashNotImplemented, /* tp_hash */ 21 | 0, /* tp_call */ 22 | 0, /* tp_str */ 23 | PyObject_GenericGetAttr, /* tp_getattro */ 24 | 0, /* tp_setattro */ 25 | 0, /* tp_as_buffer */ 26 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 27 | Py_TPFLAGS_BASETYPE, /* tp_flags */ 28 | set_doc, /* tp_doc */ 29 | (traverseproc)set_traverse, /* tp_traverse */ 30 | (inquiry)set_clear_internal, /* tp_clear */ 31 | (richcmpfunc)set_richcompare, /* tp_richcompare */ 32 | offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */ 33 | (getiterfunc)set_iter, /* tp_iter */ 34 | 0, /* tp_iternext */ 35 | set_methods, /* tp_methods */ 36 | 0, /* tp_members */ 37 | 0, /* tp_getset */ 38 | 0, /* tp_base */ 39 | 0, /* tp_dict */ 40 | 0, /* tp_descr_get */ 41 | 0, /* tp_descr_set */ 42 | 0, /* tp_dictoffset */ 43 | (initproc)set_init, /* tp_init */ 44 | PyType_GenericAlloc, /* tp_alloc */ 45 | set_new, /* tp_new */ 46 | PyObject_GC_Del, /* tp_free */ 47 | .tp_vectorcall = set_vectorcall, 48 | }; 49 | ``` 50 | 51 | ``` 52 | static void 53 | set_dealloc(PySetObject *so) 54 | { 55 | setentry *entry; 56 | Py_ssize_t used = so->used; 57 | 58 | /* bpo-31095: UnTrack is needed before calling any callbacks */ 59 | PyObject_GC_UnTrack(so); 60 | Py_TRASHCAN_BEGIN(so, set_dealloc) 61 | if (so->weakreflist != NULL) 62 | PyObject_ClearWeakRefs((PyObject *) so); 63 | 64 | for (entry = so->table; used > 0; entry++) { 65 | if (entry->key && entry->key != dummy) { 66 | used--; 67 | Py_DECREF(entry->key); 68 | } 69 | } 70 | if (so->table != so->smalltable) 71 | PyMem_DEL(so->table); 72 | Py_TYPE(so)->tp_free(so); 73 | Py_TRASHCAN_END 74 | } 75 | ``` 76 | 1. set 객체는 삭제될 때(destruction), set_dealloc 함수를 호출한다. 77 | 2. set_dealloc 함수는 가비지 컬렉터의 추적 대상에서 제외하고, 약한 참조 리스트를 클리어 하는 등의 작업을 한다. 78 | 3. 약한 참조 리스트를 클리어한다고 해서, 약한 참조 리스트에 포함되어 있는 다른 객체들의 메모리가 해제되는 것은 아니다. 79 | 80 | -------------------------------------------------------------------------------- /book/docs/12_0_standard_library.md: -------------------------------------------------------------------------------- 1 | # 12. 표준 라이브러리 2 | 3 | CPython 표준 라이브러리 모듈은 두 가지 종류로 나뉜다. 4 | 5 | 1. 유틸리티를 제공하는 순수한 파이썬 모듈 6 | 2. C로 작성됐고 파이썬 래퍼를 제공하는 모듈 7 | 8 | ## 12.1 파이썬 모듈 9 | 10 | 순수한 파이썬 모듈들은 `Lib` 디렉토리에 위치한다. 11 | 12 | 아래의 email 모듈과 같은 큰 모듈 중 일부는 하위 모듈이 있는 경우도 있다. 13 | 14 | ![library_directory](../images/12_standard_library/00_library_directory.png) 15 | 16 | 파이썬 배포판을 설치하면 표준 라이브러리 모듈은 배포판 폴더로 복사된다. 해당 폴더는 파이썬을 시작할 때 항상 경로에 포함되어 모듈을 임포트할 때 모듈 위치를 신경 쓰지 않아도 된다. 17 | 18 | → `sys.path`에 포함된다. 19 | 20 | 아래는 파이썬 모듈 중 하나인 `colorsys`의 함수이다. 21 | 22 | ```python 23 | def rgb_to_hls(r, g, b): 24 | maxc = max(r, g, b) 25 | minc = min(r, g, b) 26 | # XXX Can optimize (maxc+minc) and (maxc-minc) 27 | l = (minc+maxc)/2.0 28 | if minc == maxc: 29 | return 0.0, l, 0.0 30 | if l <= 0.5: 31 | s = (maxc-minc) / (maxc+minc) 32 | else: 33 | s = (maxc-minc) / (2.0-maxc-minc) 34 | rc = (maxc-r) / (maxc-minc) 35 | gc = (maxc-g) / (maxc-minc) 36 | bc = (maxc-b) / (maxc-minc) 37 | if r == maxc: 38 | h = bc-gc 39 | elif g == maxc: 40 | h = 2.0+rc-bc 41 | else: 42 | h = 4.0+gc-rc 43 | h = (h/6.0) % 1.0 44 | return h, l, s 45 | ``` 46 | 47 | 위 함수를 사용하는 방법은 아래와 같다. 48 | 49 | ```python 50 | import colorsys 51 | 52 | colorsys.rgb_to_hls(255, 0, 0) 53 | ``` 54 | 55 | 모듈의 위치를 신경 쓰지 않고 바로 임포트할 수 있다. 56 | 57 | 모든 파이썬 모듈은 위 함수와 같이 단순한 파이썬 코드로 이루어져 있으며 이해하기 어렵지 않다. 따라서 표준 라이브러리 코드에서 버그나 개선 사항을 찾아 파이썬 배포판에 기여할 수도 있다. 58 | 59 | ## 12.2 파이썬과 C가 혼용된 모듈 60 | 61 | 순수한 파이썬 모듈을 제외한 나머지 모듈은 모두 C로 작성됐거나 C와 파이썬이 혼용되어 있다. 62 | 63 | C로 작성된 부분은 `Modules` 디렉토리에 위치하며 파이썬으로 작성된 부분은 `Lib` 디렉토리에 위치한다. 64 | 65 | 아래 사항은 예외이다. 66 | 67 | 1. `sys` 모듈은 `Python/sysmodule.c`에 위치한다. 68 | - CPython의 내부와 강하게 연관되어 있기 때문에 `Python` 디렉토리에 존재한다. 69 | 2. `__builtins__` 모듈은 `Python/bltinmodule.c`에 위치한다. 70 | - 인터프리터를 인스턴스화할 때 내장 함수들을 __builtins__로부터 임포트하므로 `Python` 디렉토리에 존재한다. 71 | - `print()`, `chr()`, `format()`과 같은 모든 내장 함수를 해당 파일에서 찾을 수 있다. 72 | 73 | C로 작성된 일부 모듈의 내용은 운영 체제 기능을 외부에 노출한다. 따라서 운영 체제에 따라 모듈이 다르게 동작하는 특수한 케이스가 존재한다. 74 | 75 | 예를 들어 `time` 모듈은 윈도우가 시간을 유지하고 저장하는 방법이 리눅스, macOS와 전혀 다르기 때문에 운영 체제별로 시간 함수의 정확도가 다르다. 76 | 77 | 스레딩 모듈, 파일 시스템 모듈, 네트워킹 모듈도 동일한 API를 운영 체제별로 여러 번 구현한다. 78 | 79 | 운영 체제별로 동작이 다르기 때문에 CPython 소스 코드는 최대한 같은 방식으로 동작을 구현한 다음 일관성 있고 추상화된 API만 제공한다. 80 | 81 | 이러한 구현 방식을 `time` 모듈에서도 확인할 수 있다. 82 | 83 | 아래는 `time` 모듈의 함수로 프로세스의 CPU 사용 시간을 나노초 단위로 반환하는 함수이다. 84 | 85 | ```c 86 | static PyObject * 87 | time_process_time_ns(PyObject *self, PyObject *unused) 88 | { 89 | _PyTime_t t; 90 | if (_PyTime_GetProcessTimeWithInfo(&t, NULL) < 0) { 91 | return NULL; 92 | } 93 | return _PyTime_AsNanosecondsObject(t); 94 | } 95 | ``` 96 | 97 | 아래 함수는 `time_process_time_ns()`에서 호출하는 함수로 운영 체제에 따라 다른 방식으로 시스템 프로세스 시간을 가져오는 기능을 수행한다. 98 | 99 | ```c 100 | static int 101 | _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) 102 | { 103 | #if defined(MS_WINDOWS) 104 | HANDLE process; 105 | FILETIME creation_time, exit_time, kernel_time, user_time; 106 | 107 | ... 108 | 109 | t = _PyTime_FromNanoseconds((ktime + utime) * 100); 110 | *tp = t; 111 | return 0; 112 | #else 113 | 114 | /* clock_gettime */ 115 | #if defined(HAVE_CLOCK_GETTIME) \ 116 | && (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF)) 117 | struct timespec ts; 118 | 119 | ... 120 | 121 | /* clock */ 122 | /* Currently, Python 3 requires clock() to build: see issue #22624 */ 123 | return _PyTime_GetClockWithInfo(tp, info); 124 | #endif 125 | } 126 | ``` 127 | -------------------------------------------------------------------------------- /8th_members/하상천/10주차.md: -------------------------------------------------------------------------------- 1 | ## 10주차 미션 2 | 3 | ### 싱글 프로세스 + 싱글 스레드 4 | 5 | ```python 6 | from queue import Queue 7 | import socket 8 | import time 9 | 10 | timeout = 1.0 11 | 12 | 13 | def check_port(host: str, port: int, results: Queue): 14 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 15 | sock.settimeout(timeout) 16 | result = sock.connect_ex((host, port)) 17 | if result == 0: 18 | results.put(port) 19 | sock.close() 20 | 21 | 22 | def main(): 23 | start = time.time() 24 | host = "localhost" # Replace with a host you own 25 | results = Queue() 26 | for port in range(30000, 65536): 27 | check_port(host, port, results) 28 | while not results.empty(): 29 | print("Port {0} is open".format(results.get())) 30 | print("Completed scan in {0} seconds".format(time.time() - start)) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | ``` 36 | 37 | image 38 | 39 | ### 멀티스레딩 40 | 41 | ```python 42 | from threading import Thread 43 | from queue import Queue 44 | import socket 45 | import time 46 | 47 | timeout = 1.0 48 | 49 | 50 | def check_port(host: str, port: int, results: Queue): 51 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 52 | sock.settimeout(timeout) 53 | result = sock.connect_ex((host, port)) 54 | if result == 0: 55 | results.put(port) 56 | sock.close() 57 | 58 | 59 | def main(): 60 | start = time.time() 61 | host = "localhost" # Replace with a host you own 62 | threads = [] 63 | results = Queue() 64 | for port in range(30000, 65536): 65 | t = Thread(target=check_port, args=(host, port, results)) 66 | t.start() 67 | threads.append(t) 68 | for t in threads: 69 | t.join() 70 | while not results.empty(): 71 | print("Port {0} is open".format(results.get())) 72 | print("Completed scan in {0} seconds".format(time.time() - start)) 73 | 74 | 75 | if __name__ == '__main__': 76 | main() 77 | ``` 78 | 79 | image 80 | 81 | ### 멀티스레딩 + 스레드 개수 제한 82 | 83 | ```python 84 | import socket 85 | import time 86 | from concurrent.futures import ThreadPoolExecutor, as_completed 87 | from queue import Queue 88 | 89 | timeout = 1.0 90 | 91 | 92 | def check_port(host: str, port: int) -> int: 93 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 94 | sock.settimeout(timeout) 95 | result = sock.connect_ex((host, port)) 96 | if result == 0: 97 | return port 98 | return None 99 | 100 | 101 | def main(): 102 | start = time.time() 103 | host = "localhost" # Replace with a host you own 104 | open_ports = [] 105 | 106 | with ThreadPoolExecutor(max_workers=50) as executor: 107 | futures = [executor.submit(check_port, host, port) for port in range(30000, 65536)] 108 | 109 | for future in as_completed(futures): 110 | port = future.result() 111 | if port is not None: 112 | open_ports.append(port) 113 | 114 | for port in open_ports: 115 | print(f"Port {port} is open") 116 | print(f"Completed scan in {time.time() - start:.2f} seconds") 117 | 118 | 119 | if __name__ == '__main__': 120 | main() 121 | ``` 122 | 123 | image 124 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/pycharm,jupyternotebooks 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=pycharm,jupyternotebooks 3 | 4 | ### JupyterNotebooks ### 5 | # gitignore template for Jupyter Notebooks 6 | # website: http://jupyter.org/ 7 | 8 | */_build/* 9 | */__pycache__/* 10 | 11 | .ipynb_checkpoints 12 | */.ipynb_checkpoints/* 13 | 14 | # IPython 15 | profile_default/ 16 | ipython_config.py 17 | 18 | # Remove previous ipynb_checkpoints 19 | # git rm -r .ipynb_checkpoints/ 20 | 21 | ### PyCharm ### 22 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 23 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 24 | 25 | # User-specific stuff 26 | */.idea 27 | .idea/**/workspace.xml 28 | .idea/**/tasks.xml 29 | .idea/**/usage.statistics.xml 30 | .idea/**/dictionaries 31 | .idea/**/shelf 32 | 33 | # AWS User-specific 34 | .idea/**/aws.xml 35 | 36 | # Generated files 37 | .idea/**/contentModel.xml 38 | 39 | # Sensitive or high-churn files 40 | .idea/**/dataSources/ 41 | .idea/**/dataSources.ids 42 | .idea/**/dataSources.local.xml 43 | .idea/**/sqlDataSources.xml 44 | .idea/**/dynamic.xml 45 | .idea/**/uiDesigner.xml 46 | .idea/**/dbnavigator.xml 47 | 48 | # Gradle 49 | .idea/**/gradle.xml 50 | .idea/**/libraries 51 | 52 | # Gradle and Maven with auto-import 53 | # When using Gradle or Maven with auto-import, you should exclude module files, 54 | # since they will be recreated, and may cause churn. Uncomment if using 55 | # auto-import. 56 | # .idea/artifacts 57 | # .idea/compiler.xml 58 | # .idea/jarRepositories.xml 59 | # .idea/modules.xml 60 | # .idea/*.iml 61 | # .idea/modules 62 | # *.iml 63 | # *.ipr 64 | 65 | # CMake 66 | cmake-build-*/ 67 | 68 | # Mongo Explorer plugin 69 | .idea/**/mongoSettings.xml 70 | 71 | # File-based project format 72 | *.iws 73 | 74 | # IntelliJ 75 | out/ 76 | 77 | # mpeltonen/sbt-idea plugin 78 | .idea_modules/ 79 | 80 | # JIRA plugin 81 | atlassian-ide-plugin.xml 82 | 83 | # Cursive Clojure plugin 84 | .idea/replstate.xml 85 | 86 | # SonarLint plugin 87 | .idea/sonarlint/ 88 | 89 | # Crashlytics plugin (for Android Studio and IntelliJ) 90 | com_crashlytics_export_strings.xml 91 | crashlytics.properties 92 | crashlytics-build.properties 93 | fabric.properties 94 | 95 | # Editor-based Rest Client 96 | .idea/httpRequests 97 | 98 | # Android studio 3.1+ serialized cache file 99 | .idea/caches/build_file_checksums.ser 100 | 101 | ### PyCharm Patch ### 102 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 103 | 104 | # *.iml 105 | # modules.xml 106 | # .idea/misc.xml 107 | # *.ipr 108 | 109 | # Sonarlint plugin 110 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 111 | .idea/**/sonarlint/ 112 | 113 | # SonarQube Plugin 114 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 115 | .idea/**/sonarIssues.xml 116 | 117 | # Markdown Navigator plugin 118 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 119 | .idea/**/markdown-navigator.xml 120 | .idea/**/markdown-navigator-enh.xml 121 | .idea/**/markdown-navigator/ 122 | 123 | # Cache file creation bug 124 | # See https://youtrack.jetbrains.com/issue/JBR-2257 125 | .idea/$CACHE_FILE$ 126 | 127 | # CodeStream plugin 128 | # https://plugins.jetbrains.com/plugin/12206-codestream 129 | .idea/codestream.xml 130 | 131 | # Azure Toolkit for IntelliJ plugin 132 | # https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij 133 | .idea/**/azureSettings.xml 134 | 135 | # End of https://www.toptal.com/developers/gitignore/api/pycharm,jupyternotebooks 136 | 137 | !8th_members/* 138 | -------------------------------------------------------------------------------- /8th_members/김필모/10주차.md: -------------------------------------------------------------------------------- 1 | # Port Scanner 예제 실행해보기 2 | 3 | ### 싱글 프로세스 + 싱글 스레드 4 | ```python3 5 | from queue import Queue 6 | import socket 7 | import time 8 | 9 | timeout = 1.0 10 | 11 | def check_port(host: str, port: int, results: Queue): 12 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 | sock.settimeout(timeout) 14 | result = sock.connect_ex((host, port)) 15 | if result == 0: 16 | results.put(port) 17 | sock.close() 18 | 19 | def main(): 20 | start = time.time() 21 | host = "localhost" # Replace with a host you own 22 | results = Queue() 23 | for port in range(30000, 65536): 24 | check_port(host, port, results) 25 | while not results.empty(): 26 | print("Port {0} is open".format(results.get())) 27 | print("Completed scan in {0} seconds".format(time.time() - start)) 28 | 29 | if __name__ == '__main__': 30 | main() 31 | ``` 32 | Screenshot 2024-06-30 at 2 44 52 PM 33 | 34 | 35 | ### 멀티스레딩 36 | 37 | 38 | ```python3 39 | from threading import Thread 40 | from queue import Queue 41 | import socket 42 | import time 43 | 44 | timeout = 1.0 45 | 46 | def check_port(host: str, port: int, results: Queue): 47 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 48 | sock.settimeout(timeout) 49 | result = sock.connect_ex((host, port)) 50 | if result == 0: 51 | results.put(port) 52 | sock.close() 53 | 54 | def main(): 55 | start = time.time() 56 | host = "localhost" # Replace with a host you own 57 | threads = [] 58 | results = Queue() 59 | for port in range(30000, 65536): 60 | t = Thread(target=check_port, args=(host, port, results)) 61 | t.start() 62 | threads.append(t) 63 | for t in threads: 64 | t.join() 65 | while not results.empty(): 66 | print("Port {0} is open".format(results.get())) 67 | print("Completed scan in {0} seconds".format(time.time() - start)) 68 | 69 | if __name__ == '__main__': 70 | main() 71 | ``` 72 | Screenshot 2024-06-30 at 2 45 36 PM 73 | 74 | 75 | ### 멀티스레딩 + 스레드 개수 제한 76 | ```python3 77 | import socket 78 | import time 79 | from concurrent.futures import ThreadPoolExecutor, as_completed 80 | from queue import Queue 81 | 82 | timeout = 1.0 83 | 84 | 85 | def check_port(host: str, port: int) -> int: 86 | with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 87 | sock.settimeout(timeout) 88 | result = sock.connect_ex((host, port)) 89 | if result == 0: 90 | return port 91 | return None 92 | 93 | 94 | def main(): 95 | start = time.time() 96 | host = "localhost" # Replace with a host you own 97 | open_ports = [] 98 | 99 | with ThreadPoolExecutor(max_workers=50) as executor: 100 | futures = [executor.submit(check_port, host, port) 101 | for port in range(30000, 65536)] 102 | 103 | for future in as_completed(futures): 104 | port = future.result() 105 | if port is not None: 106 | open_ports.append(port) 107 | 108 | for port in open_ports: 109 | print(f"Port {port} is open") 110 | print(f"Completed scan in {time.time() - start:.2f} seconds") 111 | 112 | 113 | if __name__ == '__main__': 114 | main() 115 | 116 | ``` 117 | 118 | Screenshot 2024-06-30 at 2 46 34 PM 119 | 120 | 121 | -------------------------------------------------------------------------------- /8th_members/전희선/13주차.md: -------------------------------------------------------------------------------- 1 | ## (Chapter 14) pdb 사용해보기 2 | #### (참고) 주요 PDB 명령어 3 | - n (next): 다음 라인으로 이동 4 | - s (step): 함수 내부로 들어감 5 | - c (continue): 다음 중단점까지 실행 6 | - p (print): 변수 값 출력 7 | - l (list): 현재 위치의 코드 표시 8 | - q (quit): 디버거 종료 9 | 10 | #### test.py 11 | ```python 12 | import pdb 13 | 14 | def add(n1, n2): 15 | result = n1 + n2 16 | pdb.set_trace() 17 | return result 18 | 19 | def subtract(n1, n2): 20 | result = n2 - n1 21 | pdb.set_trace() 22 | return result 23 | 24 | a = 1 25 | b = 2 26 | c = 3 27 | d = add(a, b) 28 | e = subtract(c, b) 29 | ``` 30 | 31 | #### Result 32 | ``` 33 | ✗ python3 -m pdb test.py 34 | > /Users/user/Documents/CPython-Guide/ch14/test.py(1)() 35 | -> import pdb 36 | (Pdb) n 37 | > /Users/user/Documents/CPython-Guide/ch14/test.py(3)() 38 | -> def add(n1, n2): 39 | (Pdb) n 40 | > /Users/user/Documents/CPython-Guide/ch14/test.py(8)() 41 | -> def subtract(n1, n2): 42 | (Pdb) n 43 | > /Users/user/Documents/CPython-Guide/ch14/test.py(13)() 44 | -> a = 1 45 | (Pdb) n 46 | > /Users/user/Documents/CPython-Guide/ch14/test.py(14)() 47 | -> b = 2 48 | (Pdb) l 49 | 9 result = n2 - n1 50 | 10 pdb.set_trace() 51 | 11 return result 52 | 12 53 | 13 a = 1 54 | 14 -> b = 2 55 | 15 c = 3 56 | 16 d = add(a, b) 57 | 17 e = subtract(c, b) 58 | 18 59 | [EOF] 60 | (Pdb) n 61 | > /Users/user/Documents/CPython-Guide/ch14/test.py(15)() 62 | -> c = 3 63 | (Pdb) n 64 | > /Users/user/Documents/CPython-Guide/ch14/test.py(16)() 65 | -> d = add(a, b) 66 | (Pdb) s 67 | --Call-- 68 | > /Users/user/Documents/CPython-Guide/ch14/test.py(3)add() 69 | -> def add(n1, n2): 70 | (Pdb) n 71 | > /Users/user/Documents/CPython-Guide/ch14/test.py(4)add() 72 | -> result = n1 + n2 73 | (Pdb) n 74 | > /Users/user/Documents/CPython-Guide/ch14/test.py(5)add() 75 | -> pdb.set_trace() 76 | (Pdb) n 77 | > /Users/user/Documents/CPython-Guide/ch14/test.py(6)add() 78 | -> return result 79 | (Pdb) n 80 | --Return-- 81 | > /Users/user/Documents/CPython-Guide/ch14/test.py(6)add()->3 82 | -> return result 83 | (Pdb) n 84 | > /Users/user/Documents/CPython-Guide/ch14/test.py(17)() 85 | -> e = subtract(c, b) 86 | (Pdb) s 87 | --Call-- 88 | > /Users/user/Documents/CPython-Guide/ch14/test.py(8)subtract() 89 | -> def subtract(n1, n2): 90 | (Pdb) c 91 | > /Users/user/Documents/CPython-Guide/ch14/test.py(11)subtract() 92 | -> return result 93 | (Pdb) l 94 | 6 return result 95 | 7 96 | 8 def subtract(n1, n2): 97 | 9 result = n2 - n1 98 | 10 pdb.set_trace() 99 | 11 -> return result 100 | 12 101 | 13 a = 1 102 | 14 b = 2 103 | 15 c = 3 104 | 16 d = add(a, b) 105 | (Pdb) n 106 | --Return-- 107 | > /Users/user/Documents/CPython-Guide/ch14/test.py(11)subtract()->-1 108 | -> return result 109 | (Pdb) n 110 | --Return-- 111 | > /Users/user/Documents/CPython-Guide/ch14/test.py(17)()->None 112 | -> e = subtract(c, b) 113 | (Pdb) n 114 | --Return-- 115 | > (1)()->None 116 | (Pdb) n 117 | > /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/bdb.py(584)run() 118 | -> self.quitting = True 119 | (Pdb) n 120 | > /Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/bdb.py(585)run() 121 | -> sys.settrace(None) 122 | (Pdb) n 123 | The program finished and will be restarted 124 | > /Users/user/Documents/CPython-Guide/ch14/test.py(1)() 125 | -> import pdb 126 | (Pdb) q 127 | ``` 128 | 129 | ## (Chapter 15) cProfile 사용해보기 130 | 131 | (위 test.py에서 pdb 관련 부분만 주석 처리) 132 | ``` 133 | ✗ python3 -m cProfile test.py 134 | 5 function calls in 0.000 seconds 135 | 136 | Ordered by: standard name 137 | 138 | ncalls tottime percall cumtime percall filename:lineno(function) 139 | 1 0.000 0.000 0.000 0.000 test.py:3() 140 | 1 0.000 0.000 0.000 0.000 test.py:3(add) 141 | 1 0.000 0.000 0.000 0.000 test.py:8(subtract) 142 | 1 0.000 0.000 0.000 0.000 {built-in method builtins.exec} 143 | 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 144 | ``` 145 | ![image](https://github.com/heehehe/CPython-Guide/assets/41580746/6fa7b923-d139-487d-9f2f-6fb9b55dd677) 146 | -------------------------------------------------------------------------------- /8th_members/하상천/11주차.md: -------------------------------------------------------------------------------- 1 | ## 타입별 내부 구조 살펴보기 2 | 3 | ### List 타입 4 | 5 | - PyList_Type 6 | 7 | ```c 8 | PyTypeObject PyList_Type = { 9 | PyVarObject_HEAD_INIT(&PyType_Type, 0) 10 | "list", 11 | sizeof(PyListObject), 12 | 0, 13 | (destructor)list_dealloc, /* tp_dealloc */ 14 | 0, /* tp_vectorcall_offset */ 15 | 0, /* tp_getattr */ 16 | 0, /* tp_setattr */ 17 | 0, /* tp_as_async */ 18 | (reprfunc)list_repr, /* tp_repr */ 19 | 0, /* tp_as_number */ 20 | &list_as_sequence, /* tp_as_sequence */ 21 | &list_as_mapping, /* tp_as_mapping */ 22 | PyObject_HashNotImplemented, /* tp_hash */ 23 | 0, /* tp_call */ 24 | 0, /* tp_str */ 25 | PyObject_GenericGetAttr, /* tp_getattro */ 26 | 0, /* tp_setattro */ 27 | 0, /* tp_as_buffer */ 28 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 29 | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS, /* tp_flags */ 30 | list___init____doc__, /* tp_doc */ 31 | (traverseproc)list_traverse, /* tp_traverse */ 32 | (inquiry)_list_clear, /* tp_clear */ 33 | list_richcompare, /* tp_richcompare */ 34 | 0, /* tp_weaklistoffset */ 35 | list_iter, /* tp_iter */ 36 | 0, /* tp_iternext */ 37 | list_methods, /* tp_methods */ 38 | 0, /* tp_members */ 39 | 0, /* tp_getset */ 40 | 0, /* tp_base */ 41 | 0, /* tp_dict */ 42 | 0, /* tp_descr_get */ 43 | 0, /* tp_descr_set */ 44 | 0, /* tp_dictoffset */ 45 | (initproc)list___init__, /* tp_init */ 46 | PyType_GenericAlloc, /* tp_alloc */ 47 | PyType_GenericNew, /* tp_new */ 48 | PyObject_GC_Del, /* tp_free */ 49 | .tp_vectorcall = list_vectorcall, 50 | }; 51 | ``` 52 | 53 | - tp_new (PyType_GenericNew) 54 | 55 | ```c 56 | PyObject * 57 | PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds) 58 | { 59 | return type->tp_alloc(type, 0); 60 | } 61 | ``` 62 | 63 | - tp_alloc (PyType_GenericAlloc) 64 | 65 | ```c 66 | // PyObject_GC_Del: 가비지 컬렉션 대상 객체를 삭제하는 함수 67 | void PyObject_GC_Del(void *op) 68 | { 69 | // op를 PyGC_Head 포인터로 변환 70 | PyGC_Head *g = AS_GC(op); 71 | 72 | // 객체가 가비지 컬렉션 추적 대상이면 리스트에서 제거 73 | if (_PyObject_GC_IS_TRACKED(op)) 74 | { 75 | gc_list_remove(g); 76 | } 77 | 78 | // 현재 스레드 상태 가져오기 79 | PyThreadState *tstate = _PyThreadState_GET(); 80 | // 가비지 컬렉션 상태 가져오기 81 | GCState *gcstate = &tstate->interp->gc; 82 | 83 | // 첫 번째 세대(young generation)의 객체 수가 0보다 크면 감소 84 | if (gcstate->generations[0].count > 0) 85 | { 86 | gcstate->generations[0].count--; 87 | } 88 | 89 | // 메모리 해제 90 | PyObject_FREE(g); 91 | } 92 | ``` 93 | 94 | ### 코드 보면서 궁금한 점 95 | 96 | - CPython에서 스레드마다 가비지 컬렉션을 가지고 있는가? 97 | - No! 98 | - 각 스레드마다 완전히 독립적인 가비지 컬렉션을 가지고 있지는 않지만, 스레드별로 일부 상태를 관리 99 | - 전역 가비지 컬렉션 100 | - CPython은 기본적으로 하나의 전역 가비지 컬렉션 시스템을 가지고 있다. 이는 모든 스레드에서 공유한다. 101 | - 스레드별 상태 102 | - 각 스레드는 자체적인 `PyThreadState` 구조체를 가지고 있으며, 이 구조체 안에 `GCState`라는 필드가 있다. 이 `GCState`는 해당 스레드의 가비지 컬렉션 관련 상태 정보를 포함한다. 103 | - 스레드별로 가비지 컬렉션 카운터를 관리한다. 104 | - 가비지 컬렉션 세대(generations)에 대한 정보를 저장한다. 105 | - 스레드별 가비지 컬렉션 임계값을 설정할 수 있게 한다. 106 | - 동기화 107 | - 전역 가비지 컬렉션 작업은 GIL(Global Interpreter Lock)에 의해 보호 108 | - 정리하면 가비지 컬렉션은 하나이고, 스레드별로 가비지 컬렉션의 상태 정보, 임계값을 가지고 있어서 개별로 실행할 수 있다. 실행한 이후에는 전역 가비지 컬렉션에 반영하는데 GIL이 있기 때문에 동기화가 보호된다. 109 | -------------------------------------------------------------------------------- /book/docs/9_0_memory.md: -------------------------------------------------------------------------------- 1 | # 9. 메모리 관리 2 | 3 | - [메모리 관리](#메모리-관리) 4 | - [9.0 개요](#90-개요) 5 | - [9.1 C 메모리 할당](#91-C-메모리-할당) 6 | - [9.2 파이썬 메모리 관리 시스템의 설계](#92-파이썬-메모리-관리-시스템의-설계) 7 | - [9.3 CPython 메모리 할당자 (pymalloc)](#93-CPython-메모리-할당자) 8 | 9 |
10 | 11 | ## 9.0 개요 12 | 13 | 동적 타입 언어인 CPython에서 메모리를 어떻게 할당 하고 해제하는지 그리고 메모리 누수를 관리 하는 방법에 대해서 알아 보겠습니다. 14 |
15 | 16 | ## 9.1 C 메모리 할당 17 | 18 | ![C_memory_allocation](../images/9_memory/01_C_memory_allocation.png) 19 | 20 | 21 | CPython을 구현하는 C 언어에서의 메모리 할당은 크게 3가지로 나뉩니다. 22 | 23 | 1. 정적 메모리 할당(Static) : 컴파일 시간에 필요한 메모리가 계산되고 프로그램이 실행될 때 할당 24 | 2. 자동 메모리 할당(Stack) : 함수 실행시에 스코프에 필요한 지역 변수가 콜 스택에 할당 25 | 3. 동적 메모리 할당(Heap) : 런타임에 메모리를 동적으로 할당하며 제대로 반환하지 않으면 메모리 누수 발생 26 |
27 | 28 | ## 9.2 파이썬 메모리 관리 시스템의 설계 29 | 30 | 메모리 관점에서 파이썬 언어 설계의 특징 31 | 32 | 1. 변수의 크기를 컴파일 시간에 정할 수 없음 33 | 2. 코어 타입의 크기가 가변적임 (list, dict, int) 34 | 3. 타입이 달라도 같은 이름을 재사용 가능 35 | 36 | 파이썬 객체 메모리는 개발자가 직접 할당 하는 대신 파이썬 언어에서 제공하는 메모리 할당 API에 의해 자동으로 할당됩니다. 37 | 38 | 메모리 할당 API는 C언어의 동적 메모리 할당에 의존하여 개발되었으며 메모리 누수를 막기 위해 가비지 컬렉션과 참조 카운팅을 사용해 메모리를 자동으로 해제하는 안전장치가 추가되어 있습니다. 39 | 40 | ![Cpython_memory_hierarchy](../images/9_memory/02_cpython_memory_hierarchy.png) 41 | [이미지 출처][link01] 42 | 43 | [link01]: https://velog.io/@qlgks1/python-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC-memory-optimization 44 | 45 | CPython은 세가지 동적 메모리 할당자 도메인을 제공합니다. 46 | 47 | 1. PYMEM_DOMAIN_OBJ : 파이썬 객체 메모리 할당 48 | 2. PYMEM_DOMAIN_MEM : 레거시 API용도 https://github.com/python/cpython/blob/89867d2491c0c3ef77bc237899b2f0762f43c03c/Objects/obmalloc.c#L94C32-L94C32 49 | 3. PYMEM_DOMAIN_RAW : 시스템 힙, 대용량 메모리, 비 객체 메모리 할당 50 | 51 | PYMEM_DOMAIN_MEM,PYMEM_DOMAIN_OBJ 할당자의 경우 기본 할당자로 pymalloc을 사용하며 GIL이 있는 상태에서 사용됩니다. PYMEM_DOMAIN_RAW의 경우에는 뮤텍스를 사용하여 스레드 안정성을 확보하며 malloc을 사용하여 시스템에서 직접 메모리를 할당 받습니다. 52 | 53 | 각 도메인은 _Alloc, _Calloc, _Realoc, _Free 인터페이스를 구현합니다. 54 |
55 | 56 | ## 9.3 CPython 메모리 할당자 (pymalloc) 57 | 58 | CPython의 메모리 할당 요청은 일반적으로 아래 표와 같이 고정된 크기의 작은 메모리를 요구 합니다. 59 | 60 | | CPython OBject | Size | 61 | |------|---| 62 | | PyObject | 16byte | 63 | | PyASCIIObject | 42byte | 64 | | PyCompactUnicodeObject | 72byte | 65 | | PyLongObject | 32byte | 66 | 67 | 이러한 메모리 사용 패턴에서 메모리 할당을 위해 C언어의 malloc 및 free를 반복적으로 호출하는 경우 시스템 오버헤드를 발생 시키며 프로그램이 장기간 유지되는 경우 메모리 파편화를 유발 할 수 있습니다. 68 | 69 | CPython의 메모리 할당자는 시스템 할당자 위에 구축되어 있지만 CPython에 특화 되어 있습니다. 70 | 메모리 할당 알고리즘은 아레나/풀/블록 으로 계층화된 구조로 메모리를 할당 합니다. 71 | 72 | 73 | 74 | 75 | 1. 아레나(Arena) 76 | - 가장 큰 단위의 메모리 그룹 77 | - 256KB 단위로 할당 78 | - 시스템 페이지 크기에 맞춰 정렬 79 | - 시스템 힙에 할당 80 | - 익명 메모리 매핑을 지원 하는 시스템에서 mmap()로 할당 81 | - 아레나들은 이중 연결 리스트로 연결 되어 있음 82 | 83 | ![Cpython_memory_arena](../images/9_memory/03_arena.jpg) 84 | [이미지 출처][link02] 85 | 86 | [link02]: https://fanchao01.github.io/blog/2016/10/09/python-obmalloc/ 87 | 88 | 2. 풀(Pool) 89 | - 메모리 풀에는 같은 크기의 블록들이 저장 90 | - 풀에 담을 수 있는 블록의 최대 크기는 512byte 91 | - 풀의 크기는 4096byte(=4KB)로 고정 92 | - 아레나당 풀 개수도 64개로 고정 (64*4KB = 256KB) 93 | - 같은 단위를 가지는 풀들은 풀 테이블(이중 연결 리스트)로 연결 94 | - 풀 테이블은 크기 인덱스 i로 분할 95 | - 인덱스가 i 일 때 usedpools[i+i]는 크기 단위가 i 인 사용 중인 풀 리스트의 헤더를 가리킴 96 | - 풀이 포화 상태가 되면 usedpools 리스트에서 제거 97 | - 풀에 있는 블록이 할당 해제되면 다시 usedpools[] 리스트 맨 앞에 배치되어 다음 할당 요청에 사용 98 | - 풀의 모든 블록이 할당 해제되면 usedpools 리스트에서 제거되고 freepools 맨 앞으로 이동 99 | - 풀의 상태 100 | - 포화 : 모든 블록 할당 101 | - 사용중 : 일부 블록 할당 102 | - 미사용 : 풀은 할당 되었지만, 블록은 미 할당 103 | 104 | ![Cpython_memory_pool](../images/9_memory/04_pool.png) 105 | [이미지 출처][link03] 106 | 107 | [link03]: https://www.blog.subhashkumar.in/posts/python-memory-management/ 108 | 109 | 110 | 3. 블록(Block) 111 | - 풀 내부에서 메모리는 블록 단위로 할당 112 | - 블록은 고정 크기로 할당, 해제 113 | - 사용되지 않은 블록은 풀 내부의 freeblock 에 연결 114 | - 할당 해제된 블록은 freeblock 맨 앞에 연결 115 | - 풀이 초기화 되면 첫 두 블록은 freeblock 리스트에 연결 116 | - 블록 할당 과정 117 | - 인덱스 설정 118 | - 32bit 시스템에서는 블록 크기가 8byte 단위로 증가하므로 64가지 블록 크기 사용 가능 119 | - 64bit 시스템에서는 블록 크기가 16byte 단위로 증가하므로 32가지 블록 크기 사용 가능 120 | - 할당 요청된 크기에 따라 적합한 크기 인덱스가 결정 121 | - 할당 요청이 0 29 | 30 | static PyObject* method_fputs(PyObject* self, PyObject* args) { 31 | char *str, *filename = NULL; 32 | int bytes_copied = -1; 33 | 34 | if(!PyArg_ParseTuple(args, "ss", &str, &filename)) { 35 | return NULL; 36 | } 37 | 38 | FILE *fp = fopen(filename, "w"); 39 | bytes_copied = fputs(str, fp); 40 | fclose(fp); 41 | 42 | return PyLong_FromLong(bytes_copied); 43 | } 44 | ``` 45 | PyObject* 를 반환하는 fputs static 함수를 작성하였습니다 46 | PyObject 타입은 Python 의 객체 타입으로 **11장 객체와 타입**에서도 설명을 하고 있습니다 47 | 48 | ```c 49 | ... 50 | char *str, *filename = NULL; 51 | int bytes_copied = -1; 52 | if(!PyArg_ParseTuple(args, "ss", &str, &filename)) { 53 | return NULL; 54 | } 55 | ... 56 | ``` 57 | PyArg_ParseTuple 함수는 Python 에서 받은 인수 args를 로컬 변수로 대입합니다 58 | 2번째 인자 "ss"는 어떤 타입으로 인수를 파싱할지 설정합니다 (예제에서는 문자열, 문자열로 파싱) 59 | [[c-api arg 관련 공식 문서](https://docs.python.org/3/c-api/arg.html)] 60 | 3번째 인자부터는 가변길이 인자로 인수를 대입받을 변수들의 주소값을 차례대로 넘겨줍니다 61 | 62 | ```c 63 | FILE *fp = fopen(filename, "w"); 64 | bytes_copied = fputs(str, fp); 65 | fclose(fp); 66 | 67 | return PyLong_FromLong(bytes_copied); 68 | ``` 69 | 받은 인수값으로 파일을 열어 fputs를 수행합니다 70 | 그리고 반환값으로 PyLong_FromLong 함수를 통하여 fputs로 쓴 파일 크기를 PyObject로 반환합니다 71 | (PyLong_FromLong에 대한 부분도 11장 객체와 타입 참조) 72 | 73 | ### c 확장 모듈 초기화 함수 작성하기 74 | 위 코드에 이어서 확장 모듈 초기화 부분을 작성합니다 75 | ```c 76 | static PyMethodDef FPutsMethods[] = { 77 | {"fputs", method_fputs, METH_VARARGS, "Python interface for fputs C library function"}, 78 | {NULL, NULL, 0, NULL} 79 | }; 80 | ``` 81 | 모듈에서 정의된 메서드를 인터프리터에 알려주기위한 PyMethodDef 설정 82 | **"fputs"** - Python에서 호출되는 이름 83 | **method_fputs** - 호출되는 C 함수 84 | **METH_VARARGS** - self와 args를 인자로 받는다는 플래그 85 | ([c-api sstructures](https://docs.python.org/3/c-api/structures.html)) 86 | **마지막 문자열** - 메서드에 대한 docstring 87 | 88 | ```c 89 | static struct PyModuleDef fputsmodule = { 90 | PyModuleDef_HEAD_INIT, 91 | "fputs", 92 | "Python interface for the fputs C library function", 93 | -1, 94 | FPutsMethods 95 | }; 96 | ``` 97 | PyModuleDef 로 C 확장 모듈 자체에 대한 정보를 저장 ([PyModuleDef 문서](https://docs.python.org/3/c-api/module.html#c.PyModuleDef)) 98 | 총 9개의 멤버가 있지만 여기서는 필요한 5개만 초기화합니다 99 | 100 | **PyModuleDef_HEAD_INIT** - PyModuleDef_Base 유형의 멤버, 하나만 갖도록 권장 101 | **"fputs"** - Python C 확장 모듈 이름 (import fputs) 102 | **3번째 문자열** - 모듈에 대한 docstring 103 | **-1** - 프로그램 상태 저장에 필요한 메모리 크기, 모듈이 여러 서브 인터프리터에서 사용될 때 유용, 음수 값은 서브 인터프리터를 지원하지 않음을 나타냄 104 | **FPutsMethods** - 메서드 테이블에 대한 참조 105 | 106 | ```c 107 | PyMODINIT_FUNC PyInit_fputs(void) { 108 | return PyModule_Create(&fputsmodule); 109 | } 110 | ``` 111 | Python에서 모듈을 처음 임포트 할 때 PyInit_fputs를 호출하게 합니다 112 | PyMODINIT_FUNC은 암시적으로 세 가지 작업을 수행 113 | 1. 함수 반환형을 PyObject*로 암시적 설정 114 | 2. 특별한 연결을 선언 115 | 3. 함수를 External "C" 로 선언 (C++의 경우 C++ 컴파일러에 심볼에 대한 이름이 섞이지 않도록 지시) 116 | 117 | PyModule_Create는 PyObject* 형의 새로운 모듈 객체를 반환 118 | 인자로는 이전에 선언해둔 fputsmodule 객체의 주소를 전달 119 | 120 | ### setup.py 작성 121 | ```python 122 | from distutils.core import setup, Extension 123 | 124 | def main(): 125 | setup(name="fputs", 126 | version="1.0.0", 127 | description="Python interface for the fputs C library function", 128 | author="<개발자 이름>", 129 | author_email="your_email@gmail.com", 130 | ext_modules=[Extension("fputs", ["fputsmodule.c"])]) 131 | 132 | if __name__ == "__main__": 133 | main() 134 | ``` 135 | Python 패키지를 distutils를 사용하여 모듈을 빌드 할수 있습니다 136 | 내부에서 clang을 사용하여 빌드합니다 137 | 138 | ```shell 139 | python setup.py install 140 | ``` 141 | setup.py 작성 후 위 명령어로 실행하면 내가 만든 모듈이 빌드되고 설치됩니다 142 | -------------------------------------------------------------------------------- /8th_members/김원경/12주차.md: -------------------------------------------------------------------------------- 1 | # unittest를 이용해 나만의 Test Case 만들기 2 | 디렉토리 구조는 아래와 같이 구성했습니다. 3 | image 4 |

5 | 6 | 각 코드는 아래와 같습니다.

7 | 8 | ### game.py 9 | ```python 10 | from abc import ABC, abstractmethod 11 | 12 | 13 | class Unit(ABC): 14 | def __init__(self, _type, _name, _price): 15 | self.type = _type 16 | self.name = _name 17 | self.price = _price 18 | 19 | @abstractmethod 20 | def action(self): 21 | pass 22 | 23 | @abstractmethod 24 | def print(self): 25 | pass 26 | 27 | def get_type(self): 28 | return self.type 29 | 30 | def get_name(self): 31 | return self.name 32 | 33 | def get_price(self): 34 | return self.price 35 | 36 | 37 | class Attacker(Unit): 38 | def __init__(self, type, name, price, _type, _name, _price, _attack_point): 39 | super().__init__(type, name, price) 40 | self.at_ty = _type 41 | self.at_name = _name 42 | self.at_price = _price 43 | self.attack_point = _attack_point 44 | 45 | def action(self): 46 | return self.attack_point 47 | 48 | def print(self): 49 | print(f"[Attacker] Name: {self.at_name} (Attack point: {self.attack_point}, Price: {self.at_price})") 50 | 51 | 52 | class Miner(Unit): 53 | def __init__(self, type, name, price, _type, _name, _price, _mining_point): 54 | super().__init__(type, name, price) 55 | self.mi_ty = _type 56 | self.mi_name = _name 57 | self.mi_price = _price 58 | self.mining_point = _mining_point 59 | 60 | def action(self): 61 | return self.mining_point 62 | 63 | def print(self): 64 | print(f"[Miner] Name: {self.mi_name} (Mining point: {self.mining_point}, Price: {self.mi_price})") 65 | 66 | 67 | class ApplicationType: 68 | def __init__(self): 69 | self.unit_list_in_barracks = [] 70 | self.unit_list = [] 71 | self.curr_turn = 1 72 | self.MAX_turn = 50 73 | self.gold = 1000 74 | self.enemy_hp = 500 75 | self.flag_status = 0 76 | 77 | def __del__(self): 78 | for elem in self.unit_list_in_barracks: 79 | del elem 80 | for elem in self.unit_list: 81 | del elem 82 | 83 | def increase_turn(self): 84 | self.curr_turn += 1 85 | if self.curr_turn == self.MAX_turn: 86 | self.flag_status = 1 87 | print("You lose") 88 | 89 | def print_unit_list_in_barracks(self): 90 | for elem in self.unit_list_in_barracks: 91 | elem.print() 92 | 93 | def print_unit_list(self): 94 | for elem in self.unit_list: 95 | elem.print() 96 | 97 | def run(self): 98 | while self.flag_status == 0: 99 | sOption = self.get_command() 100 | if sOption == "1": 101 | self.hire_unit() 102 | elif sOption == "2": 103 | self.attack_to_enemy() 104 | elif sOption == "3": 105 | self.gather_money() 106 | elif sOption == "4": 107 | self.print_unit_list() 108 | elif sOption == "5": 109 | break 110 | print("Exit the program...") 111 | 112 | def get_command(self): 113 | print(f"Turn: {self.curr_turn}") 114 | print(f"Gold: {self.gold}") 115 | print(f"Enemy HP: {self.enemy_hp}\n") 116 | print("1. Hire Unit\n2. Attack to Enemy\n3. Gather Money\n4. Print Units\nInput>", end='') 117 | cmd = input() 118 | return cmd 119 | 120 | def hire_unit(self): 121 | pass 122 | 123 | def attack_to_enemy(self): 124 | pass 125 | 126 | def gather_money(self): 127 | pass 128 | 129 | ``` 130 |

131 | 132 | ### test.py 133 | ```python 134 | import unittest 135 | from unittest.mock import patch 136 | from io import StringIO 137 | 138 | from game import Attacker, Miner, ApplicationType 139 | 140 | 141 | class TestAttacker(unittest.TestCase): 142 | def test_attacker_action(self): 143 | attacker = Attacker(1, "Attacker1", 100, 1, "Attacker1", 100, 50) 144 | self.assertEqual(attacker.action(), 50) 145 | 146 | def test_attacker_print(self): 147 | attacker = Attacker(1, "Attacker1", 100, 1, "Attacker1", 100, 50) 148 | with patch('sys.stdout', new=StringIO()) as fake_out: 149 | attacker.print() 150 | self.assertEqual(fake_out.getvalue().strip(), "[Attacker] Name: Attacker1 (Attack point: 50, Price: 100)") 151 | 152 | 153 | class TestMiner(unittest.TestCase): 154 | def test_miner_action(self): 155 | miner = Miner(1, "Miner1", 100, 1, "Miner1", 100, 30) 156 | self.assertEqual(miner.action(), 30) 157 | 158 | def test_miner_print(self): 159 | miner = Miner(1, "Miner1", 100, 1, "Miner1", 100, 30) 160 | with patch('sys.stdout', new=StringIO()) as fake_out: 161 | miner.print() 162 | self.assertEqual(fake_out.getvalue().strip(), "[Miner] Name: Miner1 (Mining point: 30, Price: 100)") 163 | 164 | 165 | class TestApplicationType(unittest.TestCase): 166 | def setUp(self): 167 | self.app = ApplicationType() 168 | 169 | def test_initial_values(self): 170 | self.assertEqual(self.app.curr_turn, 1) 171 | self.assertEqual(self.app.MAX_turn, 50) 172 | self.assertEqual(self.app.gold, 1000) 173 | self.assertEqual(self.app.enemy_hp, 500) 174 | self.assertEqual(self.app.flag_status, 0) 175 | 176 | @patch('builtins.input', side_effect=['5']) 177 | def test_run(self): 178 | with patch('sys.stdout', new=StringIO()) as fake_out: 179 | self.app.run() 180 | self.assertIn("Exit the program...", fake_out.getvalue()) 181 | 182 | def test_increase_turn(self): 183 | self.app.increase_turn() 184 | self.assertEqual(self.app.curr_turn, 2) 185 | self.app.curr_turn = 49 186 | self.app.increase_turn() 187 | self.assertEqual(self.app.flag_status, 1) 188 | 189 | @patch('sys.stdout', new_callable=StringIO) 190 | def test_print_unit_list_in_barracks(self, mock_stdout): 191 | miner = Miner(1, "Miner1", 100, 1, "Miner1", 100, 30) 192 | self.app.unit_list_in_barracks.append(miner) 193 | self.app.print_unit_list_in_barracks() 194 | self.assertIn("[Miner] Name: Miner1 (Mining point: 30, Price: 100)", mock_stdout.getvalue().strip()) 195 | 196 | @patch('sys.stdout', new_callable=StringIO) 197 | def test_print_unit_list(self, mock_stdout): 198 | attacker = Attacker(1, "Attacker1", 100, 1, "Attacker1", 100, 50) 199 | self.app.unit_list.append(attacker) 200 | self.app.print_unit_list() 201 | self.assertIn("[Attacker] Name: Attacker1 (Attack point: 50, Price: 100)", mock_stdout.getvalue().strip()) 202 | ``` 203 |

204 | 205 | 실행 결과는 아래와 같습니다. 206 | image -------------------------------------------------------------------------------- /8th_members/이용우/3주차.md: -------------------------------------------------------------------------------- 1 | # 3주차 2 | ### 목차 3 | 1. [구성 상태](#구성-상태) 4 | - [딕셔너리 초기화 구성](#딕셔너리-초기화-구성) 5 | - [연관된 소스 파일 목록](#연관된-소스-파일-목록) 6 | - [런타임 구성 구조체](#런타임-구성-구조체) 7 | - [명령줄로 런타임 구성 설정하기](#명령줄로-런타임-구성-설정하기) 8 | 2. [빌드 구성](#빌드-구성) 9 | 3. [입력에서 모듈 만들기](#입력에서-모듈-만들기) 10 | - [연관된 소스 파일 목록](#연관된-소스-파일-목록) 11 | 4. [3주차 미션](#3주차-미션) 12 | - [CPython 인터프리터 실행 과정 코드 레벨로 이해하기](#cpython-인터프리터-실행-과정-코드-레벨로-이해하기) 13 | - [파이썬 세션에서 Runtime Flag 확인하기](#파이썬-세션에서-runtime-flag-확인하기) 14 | - [importlib.util.find_spec 함수를 사용해서 원하는 모듈의 위치를 찾아보기](#importlibutilfind_spec-함수를-사용해서-원하는-모듈의-위치를-찾아보기) 15 | 16 | 17 |


18 | 19 | ### 구성 상태 20 | CPython 런타임은 사용자 옵션구성(Configuration)을 설정한다. 21 | 특히 **Configuration**은 세 부분으로 나뉘어 있다. 22 | 23 | - `PyPreConfig` 딕셔너리 초기화 Configuration 24 | - `PyConfig` 런타임 Configuration 25 | - CPython 인터프리터에 같이 컴파일된 Configuration 26 | 27 | 여기서 `PyPreconfig`, `PyConfig` 구조체는 28 | `Include/cpython/initconfig.h`에서 정의한다. 29 | 30 |

31 | 32 | #### 딕셔너리 초기화 구성 33 | **딕셔너리 초기화 Configuration**은 사용자 환경 또는 운영체제와 관련된 Configuration이기에 34 | 런타임 Configuration과는 구분된다. 35 | 36 | 다음은 `PyPreConfig`의 세 가지 주요 기능이다. 37 | 1. 파이썬 메모리 할당자 설정하기 38 | 2. `LC_CTYPE` 로켈(locale)을 시스템 또는 사용자 선호 로켈로 구성 39 | 3. UTF-8 모드로 설정 40 | 41 | > Locale : 특정 지역, 국가, 또는 문화권에서 사용하는 언어 등과 같은 지역설정을 의미함. (ex. `ko-KR`) 42 | 43 | 44 | `PyPreConfig` 구조체는 다음과 같은 `int` 타입 필드들을 포함한다. 45 | 46 | | 필드 | 설명 | 47 | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | 48 | | `allocator` | `PYMEM_ALLOCATOR_MALLOC`와 같은 값을 사용해서 메모리 할당자를 선택한다.
`./configure --help`를 실행해 메모리 할당자에 대한 추가 정보를 얻을 수 있다. | 49 | | `configure_locate` | `LC_CTYPE` 로켈을 사용자 선호 로캘로 설정한다.
`0`으로 설정하면 `coerce_c_locale`과 `coerce_c_locale_warn`을 `0`으로 설정한다. | 50 | | `coerce_c_locale` | `2`로 설정하면 C 로켈을 강제로 적용한다.
`1`로 설정하면 `LC_CTYPE`을 읽은 후 강제로 적용할지 결정한다. | 51 | | `coerce_c_locale_warn` | `0`이 아니면 C 로켈이 강제로 적용될 때 경고가 발생한다. | 52 | | `dev_mode` | 개발 모드를 활성화한다. | 53 | | `isolated` | 격리 모드를 활성화한다. `sys.path`에 스크립트 디렉터리와
사용자의 사이트 패키지 디렉터리가 포함되지 않는다. | 54 | | `legacy_windows_fs_encoding` | `0`이 아니면 UTF-8 모드를 비활성화하고 파이썬 파일 시스템 인코딩을 `mbcs`로 설정한다. | 55 | | `parse_argv` | `0`이 아니면 명령줄 인자를 사용한다. | 56 | | `use_environment` | `0`보다 큰 값이면 환경 변수를 사용한다. | 57 | | `utf8_mode` | `0`이 아니면 UTF-8 모드를 활성화한다. | 58 | 59 |
60 | 61 | `Include/cpython/initconfig.h`에서 `PyPreConfig` 구조체를 찾아볼 수 있다. 62 | 63 |

64 | 65 | #### 연관된 소스 파일 목록 66 | 다음은 `PyPreConfig`와 연관된 소스 파일 목록이다. 67 | 68 | | 파일 | 용도 | 69 | | ---------------------- | ------------------------------------------------------- | 70 | |`Python/initconfig.c` | 시스템 환경에서 불러온 구성을 명령줄 플래그와 결합한다. | 71 | |`Include/cpython/initconfig.h` | 초기화 구성 구조체를 정의한다. | 72 | 73 |

74 | 75 | #### 런타임 구성 구조체 76 | `PyConfig`이라 불리는 런타임 Configuration 구조체는 다음과 같은 값들을 포함한다. 77 | - '디버그'나 '최적화'와 같은 실행 모드 플래그 78 | - 스크립트 파일이나 `stdin`, 모듈 등 실행 모드 79 | - `-X