- 예제코드는 https://github.com/iseohyun/python-tutorial에서 다운로드 받을 수 있습니다.
- 예제코드 적용 방법 및 환경설정은 여기를 참고하십시오
- VScode의 사용법 안내는 여기를 참고하십시오
목차보기
- 환경구축하기 : 실습 준비, 프로그램, 예제코드 다운로드 방법
- 시작하기 1_HelloWorld : 예제코드 실행 및 코드 보는 방법
- 변수 2_variable : 데이터를 순서대로 읽고, 쓰는(저장하는) 방법
- 출력 테크닉 3_print : 저장된 데이터를 잘(보기 좋게) 출력하는 방법
- 로직 4_Logic : 조건에 따라 실행 순서를 변경(추가, 건너뜀, 반복)하는 방법
- 함수 5_Function : 만들어진 로직을 재사용 하는 방법
- 콜렉션 6_Collections : [저장 단위 확장] 코드에 사용될 데이터를 묶음 단위로 사용하는 방법
- 모듈 7_Module : [프로그램 연계] 작성한(작성된) 코드를 파일 단위로(또는 더 큰 단위로) 가져다 쓰는 방법
- 예외 8_Exception : 프로그램 오류에 대한 대처
- 객체 9_Class : [더 큰 프로젝트] 프로그램을 순서지가 아닌 객체로(대상으로) 대하는 자세(문법)
- 표준 라이브러리 10_Std lib : 기본으로 제공되는 객체(예제)
모듈7_Module
외부에서의 호출
지금까지 하나의 문서(.py)에 함수와 로직을 넣는 예제를 보았습니다. 새로운 프로젝트를 진행 할 때, 이전에 사용했던 함수를 파일단위로 불러올 수 있습니다.
예를들어, 아래와 같이 작성된 fibo.py파일이 있습니다.
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while a < n:
print(a, end=" ")
a, b = b, a + b
print()
다음과 같이 수행합니다.
7_Module > 01_Import.pyimport fibo # 모듈을 불러옵니다. 모듈의 이름은 fibo입니다.
fibo.fib(1000) # fibo모듈의 fib함수를 수행합니다.
# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
이 외에도, 불러오는 방법이 존재합니다.
7_Module > 01-1_From.py 7_Module > 01-2_Import_all.py 7_Module > 01-3_Import_as.py 7_Module > 01-4_From_as.pyimport fibo # 모듈을 불러옵니다.
from fibo import fib, fib2 # fibo 모듈은 호출되지 않습니다.
fib(500)
from fibo import * # fibo모듈의 모든 함수를 로딩합니다. 추천하지 않습니다.
import fibo as fib #모듈의 이름을 fibo에서 fib으로 변경할 수 있습니다.
fib.fib(500)
from fibo import fib as fibonacci # fibo 모듈을 호출하지 않고, fib함수만 fibonacci로 변경하여 호출합니다.
fibonacci(500)
내장변수 (직접 선언 하지 않아도, 내부적으로 이미 선언된 변수)
내장변수 __name__을 이용하면 현재 모듈이 직접 실행되었는지, 외부에서 호출되었는지 알 수 있습니다. 직접 실행되는 경우 내장변수 __name__이 "__main__"이 됩니다.
7_Module > fibo.pyif __name__ == "__main__":
print("이 파일에서 실행되었습니다.")
분류 | 변수명 | 설명 |
---|---|---|
모듈 | __name__ | 모듈의 이름(if 현재 모듈=실행 모듈: "__main__") |
__file__ | 파일의 경로 + 파일명 | |
__doc__ | 모듈, 클래스, 함수의 "문서화 문자열(Docstring)" | |
__package__ | 패키지 이름(최상위 모듈: None) | |
__annotations__ | 변수나 함수의 타입 힌트(annotations) | |
__builtins__ | 내장 함수와 객체를 포함한 모듈(재정의 영향을 받지 않음) | |
__loader__ | 모듈읠 업로드한 로더 객체 정보 | |
__spec__ | 모듈의 import 관련 메타 데이터를 포함하는 객체 | |
__cached__ | 컴파일된 캐시 파일(.pyc)의 경로(없다면 "None") | |
__debug__ | 현재 디버그 모드인지 | |
객체 | __dict__ | 속성이 저장된 딕셔너리 |
__class__ | 객체 클래스 | |
__module__ | 클래스나 함수가 정의된 모듈 이름 | |
__slots__ | 클래스가 사용할 속성을 제한(메모리 관리 용) |
"""
이 문서는 내장 변수(built-in variables)을 설명하기 위한 파일
"""
# 1. 실행된 파일 감별
print(__name__) # "__main__" (직접 실행 시)
# 2. 파일의 위치 감별
print(__file__) # 실행 파일의 "디렉토리 + 파일명"
# 3. 문서 설명서 조회(있다면...)
print(__doc__) # "이 문서는... "
# 4. 현재 모듈
print(myPackage.__package__) # "None": 최상위 모듈
# 5. 변수나 함수의 타입힌트
def func1(name: str, age: int) -> str:
pass
print(func1.__annotations__)
# 6. 내장함수 abs와 동일한 이름의 함수를 재정의
def abs(num):
return num + 10
print(abs(-4), "/", built-ins(-4): __builtins__.abs(-4)) # -4 + 10 / |-4|
# 7. 업로드한 로더 객체 정보
print(__loader__) # <_frozen_importlib_external.SourceFileLoader object at...
# 8. 모듈의 메타 데이타
print(myPackage.__spec__) # ModuleSpec(name='__main__', ...)
# 9. 캐시 정보를 조회
print(myPackage.__cached__)
# 10. 현재 디버그 모드인지
print(__debug__) # 디버그모드 = true
참고 영역(호출 영역)
모듈을 참고 할 때, 디렉토리(저장)의 위치를 신경써 주어야 합니다. 다만, 기본적으로 참고하는 루트가 있습니다.
- sys.builtin_module_names를 검색한다.
- 현재 디렉터리를 검색한다.
- PYTHONPATH (환경변수, 유저와 프로그램이 등록한 검색할 디렉터리 목록)
- installation-dependent default (site-packages directory)
builtin모듈과 PYTHONPATH는 다음과 같이 알 수 있습니다.
7_Module > 01-7_Sys.path.py# built in 모듈
print(f"Mudule Names: {sys.builtin_module_names}")
# python path
for path in sys.path:
print(path)
내장 함수
python이 기본 제공하는 함수에 대하여 https://docs.python.org/3/library/functions.html 참조합니다.
dir함수 모듈이 가진 항목(name)을 반환합니다.
7_Module > 02_Dir.py# 내장 변수(예: __name__) 제외한 호출(import)된 모듈 조회
[item for item in dir() if not item.startswith("_")]
# 모듈을 호출하지 않고도 사용할 수 있는 함수 목록 조회
import builtins
[item for item in dir(builtins) if not item.startswith("_")]
# random모듈에 속한 모든 항목으로 리스트 작성
[item for item in dir(random) if not item.startswith("_")]
모듈을 호출하지 않고도 사용할 수 있는 내장 함수 목록은 다음과 같습니다.
ArithmeticError, AssertionError, AttributeError, BaseException, aseExceptionGroup, BlockingIOError, BrokenPipeError, BufferError, BytesWarning, ChildProcessError, ConnectionAbortedError, ConnectionError, ConnectionRefusedError, ConnectionResetError, DeprecationWarning, EOFError, Ellipsis, EncodingWarning, EnvironmentError, Exception, ExceptionGroup, False, FileExistsError, FileNotFoundError, FloatingPointError, FutureWarning, GeneratorExit, IOError, ImportError, ImportWarning, IndentationError, IndexError, InterruptedError, IsADirectoryError, KeyError, KeyboardInterrupt, LookupError, MemoryError, ModuleNotFoundError, NameError, None, NotADirectoryError, NotImplemented, NotImplementedError, OSError, OverflowError, PendingDeprecationWarning, PermissionError, ProcessLookupError, RecursionError, ReferenceError, ResourceWarning, RuntimeError, RuntimeWarning, StopAsyncIteration, StopIteration, SyntaxError, SyntaxWarning, SystemError, SystemExit, TabError, TimeoutError, True, TypeError, UnboundLocalError, UnicodeDecodeError, UnicodeEncodeError, UnicodeError, UnicodeTranslateError, UnicodeWarning, UserWarning, ValueError, Warning, WindowsError, ZeroDivisionError, abs, aiter, all, anext, any, ascii, bin, bool, breakpoint, bytearray, bytes, callable, chr, classmethod, compile, complex, copyright, credits, delattr, dict, dir, divmod, enumerate, eval, exec, exit, filter, float, format, frozenset, getattr, globals, hasattr, hash, help, hex, id, input, int, isinstance, issubclass, iter, len, license, list, locals, map, max, memoryview, min, next, object, oct, open, ord, pow, print, property, quit, range, repr, reversed, round, set, setattr, slice, sorted, staticmethod, str, sum, super, tuple, type, vars, zip
내장 함수 예제
math
7_Module > 03_Math.pyabs(-5) # 절대값
pow(4, 2) # 4^2
max(5, 12) # 최대값
min(5, 12) # 최소값
round(3.14) # 반올림
# math모듈을 import해야 하는 함수
from math import *
floor(4.99) # 내림
ceil(3.14) # 올림
sqrt(2) # 제곱근
random 난수발생
7_Module > 04_Random.pyfrom random import *
random() # 난수 생성(0 ~ 1사이의 실수 생성)
int(random() * 10) # 0 ~ 9까지 정수
randrange(1, 10) # 1 <= x < 10
randrange(1, 10, 2) # 1 <= x < 10, 홀수만
randint(1, 10) # 1 <= x <= 10
시스템 날짜
7_Module > 05_date.py 7_Module > 05-1_day of week.py 7_Module > 05-2_between.py 7_Module > 05-3_number_of_week.py 7_Module > 05-4_time zone.pyimport datetime
# 현재 시간 가져오기
current_time = datetime.datetime.now() # 예: 2024-11-28 18:31:30.848214
current_date = datetime.datetime.now().date() # 날짜만
current_time = datetime.datetime.now().time() # 시간만
# 현재 요일 가져오기
current_day = datetime.datetime.now().strftime('%A')
day_number = datetime.datetime.now().strftime('%w') # 요일을 숫자로 (e.g., Sunday = 0, Saturday = 6)
# 두 날짜간의 차이를 구함
past_date = datetime.date(2000, 1, 1)
today_date = datetime.date.today() # 오늘
difference_from_today = today_date - past_date
# 국제표준(ISO 8601 week number)에 의한 몇 번째 주인지 확인
iso_year, iso_week, iso_weekday = current_date.isocalendar()
# 협정 세계시(UTC, Universal Time Coordinated)
# 예) UTC offset: UTC-9:00
time_zone_offset = time.altzone if time.daylight else time.timezone
offset_hours = time_zone_offset // 3600
offset_minutes = (time_zone_offset % 3600) // 60
print(f"UTC offset: UTC{offset_hours:02d}:{offset_minutes:02d}")
# 시스템 타임존
# 예) "대한민국 일광 절약 시간"
time_zone_name = time.tzname[0] if time.daylight else time.tzname[1]
파일
- open('파일이름', '모드', encoding='코덱')
- 모드
- r (readonly[default]), w (writeonly, 파일 덮어씀), a (append, 추가, 끝에 붙이기)
- + (쓰기+읽기) = r+ : 앞에 추가(덮어쓰며), w+(싹다 지우고 앞부터), a+(뒤에 쓰기+읽기)
- b (binary mode): i.e. rb, wb, ab
- 코덱: (예) UTF-8, default(플랫폼 기본 설정)
f = open("test.txt", "a+", encoding="utf8")
f.write("안녕하세요\n") # 파일 마지막에 추가 작성됨
f.seek(0) # 읽기 커서를 처음으로 이동시킴
print(f.read())
f.close() # 중요: 시스템 자원을 반드시 반환해야 함
더 안전하게..
with를 이용해서 코딩하면 f.close()를 이용해서 리소스 반환을 하지 않아도 되어서 편리하고, 코드 누락이나 에러로 인한 비정상 이탈로 메모리 누수를 걱정하지 않아도 됩니다.
7_Module > 06-1_With.pywith open("test.txt", "a+", encoding="utf8") as f:
f.write("안녕하세요.\n")
f.seek(0)
print(f.read())
json 파일
json파일은 콜렉션(자료구조)를 text형식으로 저장하기 위한 방식(및 파일)로, 파싱(parsing, 구조나 의미를 파악하는 과정)의 효율을 극대화 할 수 있습니다.
7_Module > 06-4_Json.pywith open(file_path, "w+", encoding="utf-8") as f:
json.dump(dir, f)
f.seek(0)
data = f.read()
json파일의 예시
{
"dir_name": "example_directory",
"files": [
{
"file_name": "file1.txt",
"size": 1024
},
{
"file_name": "file2.txt",
"size": 2048
},
{
"file_name": "file3.txt",
"size": 512
}
]
}
직렬화
직렬화(Serialization)란 Python 객체를 바이트 스트림으로 변환하여 저장하거나 전송 가능하도록 만드는 과정입니다.
7_Module > 06-5_Pickle.pyimport pickle
profile_file = open("profile.pickle", "wb")
profile = {"이름": "이방원", "나이": 30, "취미": ["축구", "골프", "코딩"]}
pickle.dump(profile, profile_file)
profile_file.close()
예외8_Exception
예외처리란, 프로그램의 의도하지 않은 동작에 대하여, 해결방법을 제시하거나 오류 내용을 보고하도록 처리하는 기법입니다.
오류에 대한 처리를 하지 않으면, 오류가 발생하는 순간 프로그램을 종료합니다.
오류의 종류
8_Exception > 8_Exception.pya = 1 / 0 # ZeroDivisionError: 0 으로 나누려 할 때
# 이 후 실행되지 않음
a = b + 1 # NameError: 정의되지 않은 이름이라 처리 할 수 없을 때
a = "2" + 2 # TypeError: 변수의 타입으로 인해 의도가 모호할 때 "22" vs 4
오류 처리
오류가 예상되는 부분은 try로 작성하고, 오류가 발생했을 때 처리될 부분을 except로 작성합니다.
8_Exception > 02_try.pytry:
a = 1 / 0 # "0으로 나눔 오류"발생
except ZeroDivisionError:
print("에러: 0으로 나눌 수 없습니다.")
try구문 안에 있는 함수 내부에서 발생하는 오류도 잡아낼 수 있습니다.
8_Exception > 02-1_indirectly work.pydef this_fails():
x = 1 / 0
try:
this_fails()
except ZeroDivisionError as err:
print("에러 내용:", err)
모든 에러가 처리된 후에 수행할 내용은 finally에 기재합니다(오류의 발생 여부와는 상관 없습니다).
8_Exception > 03_Finally.pytry:
raise KeyboardInterrupt
except KeyboardInterrupt:
print("Caught a KeyboardInterrupt!")
finally:
print("Goodbye, world!")
고의적 발생
raise키워드를 이용하여, 고의로 예외를 발생 시킬 수 있습니다. 고의적 발생은 '선제적 대응'이 가능하며, '오류에 대한 추가 정보'를 수집할 수 있습니다.
8_Exception > 04_Raise.pytry:
raise Exception("spam", "eggs")
except Exception as inst:
print(inst)
예외 연쇄
연쇄적 발생을 통해, 수집된 정보를 외부에서 더 상세하게 체크 할 수 있습니다.
8_Exception > 04-1_Raise chaining.pydef func():
raise ConnectionError
try:
func()
except ConnectionError as exc:
raise RuntimeError("Failed to open database") from exc
사용자 정의 예외
예외처리 구조를 빌려와 사용자 정의 에러를 선언하고 사용할 수 있습니다.
8_Exception > 05-User Exception.pyclass AppError(Exception): # 기존 예외를 커스터마이징
def __init__(self, message, code=500):
super().__init__(message)
self.code = code
class DatabaseError(AppError): # ..를 다시 커스터마이징한 사용자 에러
def __init__(self, message, query=None):
super().__init__(message, code=500)
self.query = query
try:
raise DatabaseError("DB 연결 실패", query="SELECT * FROM users") # 사용자 에러 발생
except DatabaseError as e:
print(f"에러: {e}, 코드: {e.code}, 쿼리: {e.query}") # 처리
예외 그룹
병령구조의 프로그램등에서 예외 발생시 바로 예외를 수행하기 보다, 우선 수행한 후, 한 번에 예외를 처리해야한다고 할 때, group으로 처리 할 수 있습니다.
8_Exception > 06-ExceptionGroup.pydef f():
raise ExceptionGroup(
"group1",
[
OSError(1),
SystemError(2),
ExceptionGroup(
"group2",
[
OSError(3),
RecursionError(4)
]
)
]
)
try:
f()
except* OSError as e:
print("There were OSErrors")
except* SystemError as e:
print("There were SystemErrors")
출력 결과
There were OSErrors There were SystemErrors + Exception Group Traceback (most recent call last): | File "", line 2, in | f() | ~^^ | File " ", line 2, in f | raise ExceptionGroup( | ...<12 lines>... | ) | ExceptionGroup: group1 (1 sub-exception) +-+---------------- 1 ---------------- | ExceptionGroup: group2 (1 sub-exception) +-+---------------- 1 ---------------- | RecursionError: 4 +------------------------------------
add note
에러가 발생한 후에 정보를 추가 할 수 있습니다.
8_Exception > 07_Add note.pytry:
raise TypeError("bad type")
except Exception as e:
e.add_note("Add some information") # 정보 추가 1
e.add_note("Add some more information") # 정보 추가 2
raise
8_Exception > 07-1_Add note2.py
def f():
raise OSError("operation failed")
excs = []
for i in range(3):
try:
f()
except Exception as e:
e.add_note(f"Happened in Iteration {i+1}")
excs.append(e) # 추가할 내용을 list로 작성
raise ExceptionGroup("We have some problems", excs)