Python
|
파이썬(Python)은 1991년 프로그래머인 귀도 반 로섬(Guido van Rossum) 이 발표한 고급 프로그래밍 언어로, 플랫폼 독립적이며 인터프리터식, 객체지향적, 동적 타이핑(dynamically typed) 대화형 언어이다. 파이썬이라는 이름은 귀도가 좋아하는 코미디 〈Monty Python's Flying Circus〉에서 따온 것이다.
파이썬은 비영리의 파이썬 소프트웨어 재단이 관리하는 개방형, 공동체 기반 개발 모델을 가지고 있다. C파이썬 구현이 사실상의 표준이다.
Category
- Python:Libraries - Python 추천 라이브러리 목록.
- CodingGuidelines:Python - Python 스타일 가이드.
- Python:StandardLibrary - The Python Standard Library
- Python:Distribution - Python 패키지 배포 방법.
- Python:Basic - Python 기본에 대한 설명.
- Python:Performance - Python 성능 최적화.
- Python:Boolean
- Python:Class
- Python:Metaclass
- Python:MethodResolutionOrder (MRO; Method Resolution Order)
- Python:DataModel (
Python:SpecialMethod/Python:MagicMethod)-
__name__
,__str__
,__slots__
와 같은 특수 속성/메서드/오버라이드(override) 내용 정리.
-
eval
함수에 대한 설명 및 문제점. raise
, raise from
에 대한 설명 포함. - Python:@reify
- Python:@property
- Python:@overrides
with
, async with
사용법. for
, async for
사용법. requirements.txt
파일. ...
으로 표현. count: int = 0
) Native
- CPython (구글링 시 "Embedded Python"로 검색하면 된다)
- HPy - 파이썬을 위한 더 나은 C API
- Boost:Python
- pybind11
- Manylinux - Python 커뮤니티에서 개발된 리눅스 배포판들 간의 호환성을 보장하기 위한 표준화된 방법입니다.
Python Enhancement Proposals (PEP) Index
- Python Enhancement Proposals (PEP)
- PEP 8 - Style Guide for Python Code
- PEP 405 - Python Virtual Environments
- PEP 425 - Compatibility Tags for Built Distributions
- PEP 427 (wheel) - The Wheel Binary Package Format 1.0
- PEP 432 - Restructuring the CPython startup sequence (CPython 시작 시퀀스 재구성)
- PEP 440 - Version Identification and Dependency Specification
- PEP 484 - Type Hints, pyi에 해당하는 "Stub Files"에 대한 내용도 포함.
- PEP 498 - Literal String Interpolation (
f"..."
이거) - PEP 525 - Asynchronous Generators (
__aiter__
,__anext__
,async for
,typing.AsyncGenerator
) - PEP 544 - Protocols: Structural subtyping (static duck typing)
- PEP 578 - Python Runtime Audit Hooks
- PEP 685 - Comparison of extra names for optional distribution dependencies
- PEP 692 - Using TypedDict for more precise
**kwargs typing
- PEP 703 - Making the Global Interpreter Lock Optional in CPython (nogil)
- PEP 3333 - Python Web Server Gateway Interface v1.0.1
How to install
- 1. Getting Started — Python Developer's Guide
- 3. Configure Python — Python 3.10.0 documentation
- 9. Setting Compiler Flags — Python Extension Patterns 0.1.0 documentation
- Home · pyenv/pyenv Wiki · GitHub
Install required dependencies
RHEL/CentOS Linux:
Ubuntu/Debian Linux:
sudo apt-get build-dep python
sudo apt-get install libffi-dev libgdbm-dev libsqlite3-dev libssl-dev zlib1g-dev
갱신됨. 하단의 #Debian 계열 종속성 업데이트 항목 참조.
SUSE Linux
sudo zypper install automake fdupes gcc gcc-c++ gcc-fortran gdbm-devel gettext-tools gmp-devel intltool libbz2-devel libexpat-devel libffi-devel libnsl-devel lzma-devel make ncurses-devel netcfg openssl-devel pkgconfig readline-devel sqlite-devel xz zlib-devel
Python 2.7 on CentOS 6
- CentOS 6.X Python 2.7 업그레이드
- Installing python 2.7 on centos 6.3. Follow this sequence exactly for centos machine only
CentOS 에서는 yum 이라는 리눅스 패키지 관리 툴/프로그램을 이용하게 되는데 그것이 python 2.6과 매우 밀접한 연관이 있어서 마구잡이로 2.7로 업그레이드하게 되면 yum을 사용하지 못하는 문제가 생긴다.
때문에 아래와 같이 개인 계정에 맞춰 설치해야 한다.
yum groupinstall "Development tools"
yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel
## Download Python 2.7 source code & extract.
cd ~/Downloads
wget --no-check-certificate https://www.python.org/ftp/python/2.7.6/Python-2.7.6.tar.xz
tar xf Python-2.7.6.tar.xz
cd Python-2.7.6
LDFLAGS=-fPIC && ./configure --enable-shared --prefix=/home/username/local
make && make altinstall
Debian 계열 종속성 업데이트
sudo apt-get update; sudo apt-get install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
sudo apt-get install build-essential gdb lcov pkg-config \
libbz2-dev libffi-dev libgdbm-dev libgdbm-compat-dev liblzma-dev \
libncurses5-dev libreadline6-dev libsqlite3-dev libssl-dev \
lzma lzma-dev tk-dev uuid-dev zlib1g-dev
비표준 SSL 경로 추가
- (PYTHON) 비표준 위치에 SSL을 지원하는 Python 구현 복붙노트
- Stackoverflow - Building Python with SSL support in non-standard location
빌드할 때 ./configure
단계에서 --with-openssl={openssl-install-root-dir}
옵션을 추가하면 된다.
Tip
-
중요한 점은1make install
이 아닌,make altinstall
를 사용해야 한다. - 참고로
configure
의prefix
옵션은 절대경로로 입력해야 한다. 그렇지 않으면 다음과 같은 에러를 확인할 수 있다.configure: error: expected an absolute directory name for --prefix: ~/local
기존 Python 의 컴파일 옵션 확인 방법
Python:sysconfig 에서 확인 가능. 간단히:
Python compile
프로그램 시작(load) 시간을 줄이기 위해, 바이트 컴파일된 pyc
파일을 사용 가능하다. 컴파일 방법은 아래와 같이 커맨드라인 인터프리터에서 특정 파일을 컴파일 할 수도 있고,
현재 디렉토리의 모든 *.py
파일을 컴파일할 수도 있다.
Python files
- .py pyc *.pyo 무슨차이?
- Python tutorial: Modules
- What does python file extensions, .pyc .pyd .pyo stand for?
파이선 관련 파일에 대하여 설명한다.
-
*.py
는 파이썬 텍스트 소스파일이다. -
*.pyc
는 컴파일된 파이썬 바이너리 파일이다.-O
옵션을 통해 생성 가능하다. -
*.pyo
는 최적화된(Optimized) 컴파일된 파이썬 바이너리 파일이다.-OO
옵션을 통해 생성 가능하다. -
*.pyd
는 기본적으로 Windows DLL 파일이다.2
Bootstrap script
#!/usr/bin/env bash
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" || exit; pwd)
OPY_PATH=$(which opy 2> /dev/null)
PYTHON3_PATH=$(which python3 2> /dev/null)
PYTHON_PATH=$(which python 2> /dev/null)
function run_base_python
{
if [[ -x "$OPY_PATH" ]]; then
"$OPY_PATH" "$@"
elif [[ -x "$PYTHON3_PATH" ]]; then
"$PYTHON3_PATH" "$@"
elif [[ -x "$PYTHON_PATH" ]]; then
"$PYTHON_PATH" "$@"
else
echo "The python executable could not be found." 1>&2
exit 1
fi
}
VENV_HOME=$ROOT_DIR/.venv
VENV_PYTHON=$VENV_HOME/bin/python3
if [[ ! -d "$VENV_HOME" ]]; then
run_base_python -m venv "$VENV_HOME"
if [[ -x "$VENV_PYTHON" ]]; then
"$VENV_PYTHON" -m pip install -r "$ROOT_DIR/requirements.txt"
fi
fi
if [[ ! -x "$VENV_PYTHON" ]]; then
echo "The venv's python executable could not be found." 1>&2
exit 1
fi
export PYTHONPATH
PYTHONPATH=$ROOT_DIR:$PYTHONPATH
"$VENV_PYTHON" "$@"
Python Compile
Dunder
Dunder (Double Underscore). 파이썬에서 __name__
와 같이 특수한 용도로 사용되는 심볼들을 통칭한다.
subclasshook
반드시 클래스 메서드로 정의되어야 합니다.
하위 클래스가 이 ABC의 하위 클래스로 간주되는지 확인하십시오. 이는 ABC의 하위 클래스로 간주하려는 모든 클래스에 대해 Register()를 호출할 필요 없이 issubclass()의 동작을 추가로 사용자 정의할 수 있음을 의미합니다. (이 클래스 메서드는 ABC의 subclasscheck() 메서드에서 호출됩니다.)
이 메서드는 True, False 또는 NotImplemented를 반환해야 합니다. True를 반환하면 하위 클래스는 이 ABC의 하위 클래스로 간주됩니다. False를 반환하는 경우 하위 클래스는 일반적으로 ABC의 하위 클래스인 경우에도 이 ABC의 하위 클래스로 간주되지 않습니다. NotImplemented를 반환하면 일반적인 메커니즘을 사용하여 하위 클래스 검사가 계속됩니다.
os.PathLike 예시:
class PathLike(abc.ABC):
"""Abstract base class for implementing the file system path protocol."""
@abc.abstractmethod
def __fspath__(self):
"""Return the file system path representation of the object."""
raise NotImplementedError
@classmethod
def __subclasshook__(cls, subclass):
if cls is PathLike:
return _check_methods(subclass, '__fspath__')
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
cause
raise ... from e
처럼 from 으로 지정된 예외를 획득할 수 있다.
try:
try:
raise ValueError("원래 예외")
except ValueError as e:
raise RuntimeError("새로운 예외") from e
except RuntimeError as new_exception:
original_exception = new_exception.__cause__
print(f"새 예외: {new_exception}")
print(f"원래 예외: {original_exception}")
class_getitem
Python:typing#Generics 항목 참조.
init_subclass
Python:typing#Generics 항목 참조.
Structural Pattern Matching (match ~ case 문)
파이썬 3.10 부터 도입된 문법이다. match
~ case
문.
match subject:
case <pattern_1>:
<action_1>
case <pattern_2>:
<action_2>
case <pattern_3>:
<action_3>
case _:
<action_wildcard>
- Unpacking
- Starred unpacking
- Partial assignment
- Class & Class attribute matching
- Complex pattern with wildcard
- Guard
Getter and Setter
Python:@property#Getter and Setter 항목 참조.
Make Python stack overflow and core dump
import sys
def recursive_sum(x):
return x + recursive_sum(x - 1) if x > 0 else 0
print(f'Default sys.getrecursionlimit()={sys.getrecursionlimit()}')
print(f'recursive_sum(100)={recursive_sum(100)}')
print(f'recursive_sum(1000)={recursive_sum(1000)}')
String interpolation
자세한 내용은 String interpolation 항목 참조.
Python 모듈(PIP 패키지)기반 동적 플러그인 개발 기법
- Stackoverflow - Using pip to install a program while running
- Creating and discovering plugins — Python Packaging User Guide
- simple-plugin-loader · PyPI - Dynamically load other python modules to your project
- Youtube - Python Plugin System: Load Modules Dynamically With "importlib"
간단 요약:
- pkgutil.iter_modules를 사용하여 패키지 검색.
- importlib.import_module를 사용하여 패키지 임포트.
종종 Python 응용 프로그램이나 라이브러리를 만들 때 플러그인 을 통해 사용자 지정 또는 추가 기능을 제공하는 기능을 원할 것 입니다. Python 패키지는 별도로 배포할 수 있으므로 응용 프로그램이나 라이브러리 에서 사용 가능한 모든 플러그인 을 자동으로 검색 할 수 있습니다.
자동 플러그인 검색에는 세 가지 주요 접근 방식이 있습니다:
- 명명 규칙 사용
- 네임스페이스 패키지 사용
- 패키지 메타데이터 사용
명명 규칙 사용
import importlib
import pkgutil
discovered_plugins = {
name: importlib.import_module(name)
for finder, name, ispkg
in pkgutil.iter_modules()
if name.startswith('flask_')
}
가장 추천하는 방법. (디버깅이 가장 편하다)
네임스페이스 패키지 사용
import importlib
import pkgutil
import myapp.plugins
def iter_namespace(ns_pkg):
# Specifying the second argument (prefix) to iter_modules makes the
# returned name an absolute name instead of a relative one. This allows
# import_module to work without having to do additional modification to
# the name.
return pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + ".")
discovered_plugins = {
name: importlib.import_module(name)
for finder, name, ispkg
in iter_namespace(myapp.plugins)
}
WARNING |
네임스페이스 패키지는 복잡한 기능이며 이를 생성하는 여러 가지 방법이 있습니다. 패키징 네임스페이스 패키지 문서 를 읽고 프로젝트의 플러그인에 어떤 접근 방식이 선호되는지 명확하게 문서화하는 것이 좋습니다. |
WARNING |
이 방법은 PyCharm에서 디버깅시 소스코드 Root 디렉토리 설정에 대한 충돌 오류가 발생될 수 있다. |
패키지 메타데이터 사용
setuptools의 setup.py
에서 진입점을 설정한다.
등록된 모든 진입점을 검색하고 로드할 수 있습니다:
import sys
if sys.version_info < (3, 10):
from importlib_metadata import entry_points
else:
from importlib.metadata import entry_points
discovered_plugins = entry_points(group='myapp.plugins')
WARNING |
이 방법은 패키지를 반드시 설치해야 한다. |
난독화 (Obfuscation)
- Hello world 난독화하기. (번역)
- Stackoverflow: Python Code Obfuscation (closed)
- Stackoverflow - How do I protect Python code from being read by users?
- bii internals: Compiling your python application with Cython
배포시 바이너리로 만든다. Cython, Nuitka, Shed Skin 와 같은 도구를 사용하여 C코드를 컴파일한다.
상단의 #난독화 (Obfuscation) 라이브러리 항목도 참조.
Download package
아래와 같은 방법으로 전체 패키지 파일을 획득할 수 있다.
Python underscore
- [추천] 파이썬 언더스코어(_)에 대하여 3
dunder 항목 참조.
Python gdb debugging
C 레벨의 Runtime Error 가 발생될 경우 정상적인 StackTrace 를 보기 힘들다. 이 경우 Gdb#Python gdb debugging 항목 참조.
Debugging Mode 확인 방법
# -*- coding: utf-8 -*-
import sys
def is_debugging_mode() -> bool:
"""
Return if the debugger is currently active
"""
get_trace = getattr(sys, "gettrace", lambda: None)
return get_trace() is not None
future.annotations.compiler_flag
__future__.annotations.compiler_flag
포터블하게 획득하는 방법:
# -*- coding: utf-8 -*-
from importlib import import_module
def get_annotations_compiler_flag() -> int:
future = import_module("__future__")
assert future is not None
annotations = getattr(future, "annotations")
assert annotations is not None
compiler_flag = getattr(annotations, "compiler_flag")
assert isinstance(compiler_flag, int)
return compiler_flag
파이썬 악의축 회피를 위한 주의사항
기본 인자에 함수 사용 금지
from datetime import datetime
from time import sleep
def get_update_task_query_by_uid(
updated_at=datetime.now().astimezone(),
):
print(updated_at)
get_update_task_query_by_uid()
sleep(1)
get_update_task_query_by_uid()
sleep(1)
get_update_task_query_by_uid()
sleep(1)
get_update_task_query_by_uid()
sleep(1)
위의 코드에서 updated_at
인자는 최초에 datetime.now().astimezone()
를 한 번 초기화 되고 그 이후로 호출되지 않는다.
따라서 Optional[datetime] = None
과 같이 사용하는 것이 좋다.
참고로 위 코드를 실행하면 다음과 같이 출력된다.
2021-10-07 16:44:12.581059+09:00
2021-10-07 16:44:12.581059+09:00
2021-10-07 16:44:12.581059+09:00
2021-10-07 16:44:12.581059+09:00
클래스 멤버 초기화는 인스턴스가 아님
클래스 멤버를 초기화 할 경우 이 것을 멤버 초기화로 착각해선 안된다:
class _Test0:
value = list()
class _Test1(_Test0):
def __init__(self):
pass
a = _Test1()
a.value.append(0)
b = _Test1()
b.value.append(1)
b.value.append(2)
c = _Test1()
c.value = [3, 4]
d = _Test1()
d.value.append(5)
_Test1.value.append(100)
print(a) # [0, 1, 2, 5, 100]
이건 POD 데이터 타입도 마찬가지 이다.
class _Test0:
value = 100
class _Test1(_Test0):
def __init__(self):
pass
a = _Test1()
b = _Test1()
print(a.value) # 100
print(b.value) # 100
_Test1.value = 200
print(a.value) # 200
print(b.value) # 200
Mixin 클래스의 자동 초기화
Python:Mixin#Mixin 클래스의 자동 초기화 방법 항목 참조.
Cheat Sheet
- Python 3 Cheat Sheet
- https://perso.limsi.fr/pointal/_media/python:cours:mementopython3-english.pdf
-
Memento-python3-english.pdf
인자에 대한 제한
키워드 인자만 가능하도록 제한
위치 인자가 끝나는 지점에 '*'를 붙인다.
위치 인자만 가능하도록 제한
Python에서 함수 정의 시 인자 목록의 끝에 '/'를 붙이는 것은 함수의 매개변수가 위치 인자로만 받아들이도록 강제하는 것입니다. 이것은 Python 3.8에서 새롭게 추가된 문법입니다.
"is None" vs "
None" == python 에서 None
비교를 is None
으로 하는데, == None
으로 하지 않는 이유는?
-
is
연산자 - 두 객체가 같은 메모리 위치를 참조하는지 확인합니다.
- 즉, 두 객체가 동일한 객체(identical)인지 확인합니다.
- 예:
x is y
는id(x) == id(y)
와 동일합니다.
-
==
연산자 - 두 객체의 값(value)이 같은지를 확인합니다.
- 이는 객체의
__eq__
메서드를 호출하여 비교합니다. - 따라서 두 객체가 다른 메모리 위치에 있지만 값이 같으면
True
가 될 수 있습니다.
- 이는 객체의
-
None
은 단일 객체- None은 파이썬에서 하나의 전역적인 싱글톤 객체입니다. 즉, None은 프로그램 실행 중 항상 같은 메모리 주소를 가지는 하나의 객체입니다.
- 따라서 is None을 사용하는 것이 더 직관적이고 정확합니다.
is None
의 장점- 성능:
is
는 객체의 ID를 단순 비교하기 때문에 더 빠릅니다. - 의도 명확성:
is None
은 "이 객체가 None인지 확인"이라는 명확한 의미를 전달합니다. - 반면,
== None
은__eq__
를 호출하기 때문에 오버로딩된 메서드의 영향을 받을 수 있어 의도와 다르게 동작할 가능성이 있습니다.
Example
- OpenCV-Python
- Caffe:Python
- MaskRCNN:Example:VideoReadWrite: Mask R-CNN 데모를 위한 Video Read & Write Python example.
- MaskRCNN:Example:ExcelReport: Mask R-CNN 결과 리포팅을 Excel파일로 출력한다.
- COCOAPI#UnionPolygons - 전체
annotations
목록의segmentation
영역을 병합하는 Python코드. - HTTP:Authentication#Python example - HTTP Basic Authentication 의 Python 파싱 클래스.
- MusicXML:Scripts:Mxl2Svg - mxl -> guido -> svg 변환 Python 스크립트.
Main module
이것이 뜻하는 의미는 C:/Python> python mod1.py
처럼 직접 이 파일을 실행시켰을 때는 __name__ == "__main__"
이 참이 되어 if
문 다음 문장들이 수행되고,
대화형 인터프리터나 다른 파일에서 이 모듈을 불러서 쓸때는 __name__ == "__main__"
이 거짓이 되어 if
문 아래문장들이 수행되지 않도록 한다는 뜻이다.
Current script name
- Stackoverflow: Get the name of current script with Python
- Python 101: How to Find the Path of a Running Script
__main__
이 호출된 모듈은 아래와 같이 획득할 수 있다.
import __main__ as main
print(main.__file__)
## Absolute path:
import os
print os.path.abspath(main.__file__)
현재 파일(스크립트)이름을 획득하는 방법은 아래와 같다.
Encoding setting
스크립트 파일 첫 번째 줄에 파일의 인코딩을 명시해주면 된다.
Method Overload
@overload
def get(self, key: _KT) -> Optional[_VT_co]: ...
@overload
def get(self, key: _KT, default: Union[_VT_co, _T]) -> Union[_VT_co, _T]: ...
Split key-value tokens
아래와 같은 문자열을 분석하여...
아래와 같은 사전형으로 반환한다.
구현된 함수는 아래와 같다.
def split_option(text: str, kv_split='='):
i = text.find(kv_split)
if i == -1:
return None
return text[0:i].strip(), text[i+1:].strip()
def str_to_dict(text: str, item_split=';', kv_split='='):
items = [x for x in text.split(item_split)]
items = list(filter(lambda x: x.strip(), items))
result = {}
for x in items:
opt = split_option(x, kv_split)
if opt:
assert len(opt) == 2
result[opt[0]] = opt[1]
return result
위의 사전형을 다시 문자열로 합치는 함수는 아래와 같다.
from functools import reduce
def dict_to_str(items: dict, item_split=';', kv_split='='):
return reduce(lambda x, y: x+item_split+y,
[str(k)+kv_split+str(v) for k, v in items.items()])
Appending to Your PYTHONPATH
코드상에서 PYTHONPATH
를 추가하는 방법은 아래와 같다.
적용된 PYTHONPATH
목록을 확인하는 방법은 아래와 같다.
사용 예제는 아래와 같다.
import os.path as osp
import sys
def add_path(path):
if path not in sys.path:
sys.path.insert(0, path)
this_dir = osp.dirname(__file__)
# Add caffe to PYTHONPATH
caffe_path = osp.join(this_dir, '..', 'python')
add_path(caffe_path)
Python STDOUT Buffer
환경변수 PYTHONUNBUFFERED
를 참조.
Check platform
Generics
제네릭 클래스 작성 방법은 Python:typing#Generics 항목 참조.
Checking File Permissions
import os
os.access('my_file', os.R_OK) # Check for read access
os.access('my_file', os.W_OK) # Check for write access
os.access('my_file', os.X_OK) # Check for execution access
os.access('my_file', os.F_OK) # Check for existence of file
Python version which command
def which(program):
path = os.getenv('PATH')
for cursor in path.split(os.path.pathsep):
cursor = os.path.join(cursor, program)
if os.path.exists(cursor) and os.access(cursor, os.X_OK):
return cursor
return ''
Python version variable
import sys
version_info = sys.version_info
version_text = f"{version_info[0]}.{version_info[1]}.{version_info[2]}"
print(version_text)
Elapsed Time Calculator
경과 시간 (Duration) 구하는 방법은 Python:time#Elapsed Time Calculator 항목 참조.
Input
다만 input()
을 사용할 경우 이미 선언한 Python 변수명을 사용할 수 있다.
가장 Bytes Copy 방법
밴치마크 코드는 다음과 같다:
import copy
import timeit
original_bytes = b"some bytes data" * 1000
def using_bytes_constructor():
return bytes(original_bytes)
def using_slicing():
return original_bytes[:]
def using_bytearray():
return bytearray(original_bytes)
def using_copy():
return copy.copy(original_bytes)
def using_memoryview():
return memoryview(original_bytes).tobytes()
# Benchmark each method
count = 10_000_000
print("Using slicing:", timeit.timeit(using_slicing, number=count))
print("Using bytearray:", timeit.timeit(using_bytearray, number=count))
print("Using copy:", timeit.timeit(using_copy, number=count))
print("Using memoryview:", timeit.timeit(using_memoryview, number=count))
print("Using bytes constructor:", timeit.timeit(using_bytes_constructor, number=count))
AMD Ryzen 7 4700U CPU 2.0GHz 에서 테스트한 결과:
- Using slicing: 0.7010392720003438
- Using bytearray: 4.187463062000461
- Using copy: 2.724746272999255
- Using memoryview: 4.6049892060000275
- Using bytes constructor: 1.6053336320001108
결과, Slicing 이 가장 빠르다.
Bytes 와 HEX 문자열 상호 변환
bytes to HEX String
HEX String to bytes
Integer를 Bytes로 직렬화
data = 9999
serialized_data = data.to_bytes(4, "big", signed=False)
print(serialized_data.hex()) ## 0000270f
result = int.from_bytes(serialized_data, "big", signed=False)
print(result) ## 9999
Python:struct를 사용한 방식으로 변환하고 싶다면 Python:struct#Integer를 Bytes로 직렬화 항목을 참조.
Current working directory
Return a string representing the current working directory.
List of files
import os
import re
def get_child_directories(path=os.curdir):
result = []
for parent, sub_dirs, files in os.walk(path):
result.append(parent)
return result
def get_children(path=os.curdir):
result = []
for parent, sub_dirs, files in os.walk(path):
for name in files:
# result.append(os.path.join(os.path.abspath(parent), name))
result.append(os.path.join(parent, name))
return result
def get_children_with_match(path=os.curdir, regexp='.*'):
result = []
for cursor in get_children(path):
if not re.match(regexp, cursor) is None:
result.append(cursor)
return result
def get_files(path=os.curdir):
return list(filter(lambda x: os.path.isfile(os.path.join(path, x)), os.listdir(path)))
def get_dirs(path=os.curdir):
return list(filter(lambda x: os.path.isdir(os.path.join(path, x)), os.listdir(path)))
Command-Line Arguments
import sys
print 'Number of arguments:', len(sys.argv), 'arguments.'
print 'Argument List:', str(sys.argv)
staticmethod vs classmethod
아래와 같이 staticmethod와 classmethod를 추가할 수 있다.
class Object:
@staticmethod
def method(content):
print content
factor = 1
@classmethod
def mul(cls, x):
return cls.factor*x
- staticmethod는 C++의 의 그것과 동일합니다. class는 그냥 이름만 빌려준것이고 일종의 namespace로 함수를 구현하는 것이고 instance에서는 실행되지 않습니다.
- classmethod는 인자로 클래스 자기자신을 받게 되어있습니다. 관습적으로 cls라고 표기를 합니다. 그래서 instance에서 호출을 하면, class을 인자로 넘겨주게 됩니다.
args and kwargs
Python:Function#args and kwargs 항목 참조.
instance check
Type을 검사하는 방법은 아래와 같다.
x = 'string'
isinstance(x, basestring) # Python 2.x, you would do
isinstance(x, str) # In Python 3.x, it would be
isinstance(x, unicode) # In Python 3.x, it would be
isinstance(x, list)
# ...
Print class information
클래스의 프로퍼티 목록을 출력하는 방법은 아래와 같다.
Print class member variables
클래스의 멤버 변수 목록을 출력하는 방법은 아래와 같다.
access class property from string
문자열로 클래스의 속성을 접근하는 방법은 다음과 같다:
-
getattr(x, 'y')
is equivalent tox.y
-
setattr(x, 'y', v)
is equivalent tox.y = v
-
delattr(x, 'y')
is equivalent todel x.y
Forward declarations (클래스 안에서 동일한 클래스 타입을 참조)
Inside of the class, the class is not defined yet, causing a NameError
(and PyCharm to complain).
To get around this, use forward declarations: def foo_method(self, other_foo: "Foo"):
return "Hello World!"
</syntaxhighlight>
Basically, if a type annotations is a string, it is eval
ed after the whole module is loaded, so it can evaluate to the Foo
class.
Execute a string
문자열을 직접 실행하는 방법은 아래와 같다.
Singleton
class SingletonInstane:
__instance = None
@classmethod
def __getInstance(cls):
return cls.__instance
@classmethod
def instance(cls, *args, **kargs):
cls.__instance = cls(*args, **kargs)
cls.instance = cls.__getInstance
return cls.__instance
class MyClass(BaseClass, SingletonInstane):
pass
c = MyClass.instance()
Environment variables in Python
- Stackoverflow: How to set environment variables in Python
- How to Set and Get Environment Variables in Python
환경변수 사용방법은 아래와 같다.
import os
# Set environment variables
os.environ['API_USER'] = 'username'
os.environ['API_PASSWORD'] = 'secret'
# Get environment variables
USER = os.getenv('API_USER')
PASSWORD = os.environ.get('API_PASSWORD')
# Getting non-existent keys
FOO = os.getenv('FOO') # None
BAR = os.environ.get('BAR') # None
BAZ = os.environ['BAZ'] # KeyError: key does not exist.
Python install path
파이선 설치 경로는 아래와 같이 간접적으로 확인할 수 있다.
>>> import sys
>>> sys.path
['', '/Users/username/Project/opm/python', '/Library/Python/2.7/site-packages/scons-2.3.0', ... ]
Path of imported module
Find Python libraries
파이선 라이브러리를 찾는 방법은 해당 항목을 참조.
Python PIPE
- Stackoverflow - Python read named PIPE
- Stackoverflow - Create a temporary FIFO (named pipe) in Python?
import os
import errno
FIFO = 'mypipe'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
As others have pointed out, there is no built-in mount function. However, it is easy to create one using ctypes, and this is a bit lighter weight and more reliable than using a shell command.
python 에서 mount 하는 방법
Here's an example:
import ctypes
import ctypes.util
import os
libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True)
libc.mount.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_char_p)
def mount(source, target, fs, options=''):
ret = libc.mount(source.encode(), target.encode(), fs.encode(), 0, options.encode())
if ret < 0:
errno = ctypes.get_errno()
raise OSError(errno, f"Error mounting {source} ({fs}) on {target} with options '{options}': {os.strerror(errno)}")
mount('/dev/sdb1', '/mnt', 'ext4', 'rw')
Python 에서 User(사용자) 변경 방법
다음 함수들 참조.
-
os.getgid()
-
os.getuid()
-
os.setgid()
-
os.getuid()
또는 Stackoverflow - Changing user within python shell 페이지 참조.
사용자 이름기반으로 UID 취득하고 싶다면 Python:pwd 패키지 참조.
Dict 상속 방법
소멸자 구현 방법
자세한 내용은 weakref.finalize 항목 참조.
site-packages 확인 방법
다음과 같은 방법이 있다.
-
python -m site
-
python -c 'import site; print(site.getsitepackages())'
-
python3 -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'
-
python -m site --user-site
User Directory/Data
다음 라이브러리 중 하나를 사용하거나
- appdirs - A small Python module for determining appropriate platform-specific dirs, e.g. a "user data dir".
- appdata - AppData is a Python library to access app data paths based on the operating system the app is running on.
예제의 함수를 구현:
import sys
import logging
import pathlib
from typing import Optional, Union, List, Tuple
logger = logging.getLogger(__name__)
def get_user_data_dir(appending_paths: Union[str, List[str], Tuple[str, ...]] = None) \
-> pathlib.Path:
"""
Returns a parent directory path where persistent application data can be stored.
Can also append additional paths to the return value automatically.
Linux: ~/.local/share
macOS: ~/Library/Application Support
Windows: C:/Users/<USER>/AppData/Roaming
:param appending_paths: Additional path (str) or paths (List[str], Tuple[str]) to append to return value
:type appending_paths: Un
:return: User Data Path
:rtype: str
"""
logger.debug(f'Getting Home Path...')
home = pathlib.Path.home()
logger.debug(f'Home Path: {home}')
system_paths = {
'win32': home / 'AppData/Roaming',
'linux': home / '.local/share',
'darwin': home / 'Library/Application Support'
}
logger.debug(f'Getting System Platform...')
if sys.platform not in system_paths:
raise SystemError(f'Unknown System Platform: {sys.platform}. Only supports {", ".join(list(system_paths.keys()))}')
data_path = system_paths[sys.platform]
if appending_paths:
if isinstance(appending_paths, str):
appending_paths = [appending_paths]
for path in appending_paths:
data_path = data_path / path
logger.debug(f'System Platform: {sys.platform}')
logger.debug(f'User Data Directory: {system_paths[sys.platform]}')
logger.debug(f'Return Value: {data_path}')
return data_path
Read-only property
This will make Foo.number
a read-only property:
class MetaFoo(type):
@property
def number(cls):
return cls.x
class Foo(object, metaclass=MetaFoo):
x = 4
print(Foo.number)
# 4
Foo.number = 6
# AttributeError: can't set attribute
Python 에서 2025년의 데이터 검증 환경
- 데이터 유형 확인, 누락된 값 수 확인, 비정상적인 값 탐지
왜 데이터 검증이 중요한가
- 공공기관의 분석 작업은 다음 두 가지로 나뉨:
- 애드혹 분석 – 일회성 분석 작업
- 정기 통계 생성 – 정기적으로 새로운 데이터 수집 및 처리
주요 데이터 검증 도구
- Great Expectations - Data Quality 를 위한 오픈소스 프레임워크
- Pointblank - 2024년 출시된 최신 Python 데이터 검증 도구 (RStudio → Posit 제작)
- Pandera - Great Expectations와 유사한 API 제공
- Pydantic - 데이터프레임이 아닌 딕셔너리 기반 검증 도구
- Cerberus - 딕셔너리 기반 검증 도구
- jsonschema - JSON 데이터 검증 도구
공공 부문에서 어떤 도구를 사용할 것인가
- 데이터프레임 또는 데이터베이스 검증:
- 생산 시스템에서 사용 → Great Expectations 추천
- 간단한 검증 → Pandera 추천
- 최신 도구 시도 → Pointblank 추천
- 비정형 데이터 → Pydantic 추천
- jsonschema 추천
- Cerberus 추천
Troubleshooting
TypeError: 'type' object is not subscriptable
예를 들어, dict[int]
와 같은 타입 인자를 제거하여 dict
와 같이 변경.
TypeError: get() takes no keyword arguments
함수에 사용된 키워드 인자를 제거.
예를 들어, get(size=10)
와 같이 사용되었다면 get(10)
로 변경.
TypeError: 'method' object is not subscriptable
대괄호[...]
와 괄호(...)
를 잘 사용하였는지, Type Annotation 을 사용할 수 없는 위치에 사용했는지 등 확인하자.
예를 들어 다음과 같은 코드가 있을 때:
SimpleQueue[bytes]
는 SimpleQueue
로 사용해야 한다.
UnicodeDecodeError
import codecs
with codecs.open(file_name, 'r', encoding='utf-8', errors='ignore') as f:
print(f.read())
Unsafe use of relative rpath
- FEniCS 1.6.0 binary for OS X does not work on El Capitan (unsafe use of relative rpath in libdolfin.dylib)
- install_name_tool#Unsafe use of relative rpath
Mac OSX에서 특정 라이브러리를 import
할 경우 아래와 같은 현상이 발생할 수 있다.
ImportError: dlopen(/Users/username/Project/fast-rcnn/tools/../caffe-fast-rcnn/python/caffe/_caffe.so, 2): Library not loaded: libboost_system.dylib
Referenced from: /Users/username/Project/fast-rcnn/libboost_thread.dylib
Reason: unsafe use of relative rpath libboost_system.dylib in /Users/username/Project/fast-rcnn/libboost_thread.dylib with restricted binary
이 때, 해당 라이브러리의 install name을 변경하여 해결할 수 있지만, 간단한 해결책은 아래와 같이 Python 바이너리를 복사면 된다.
$ cp System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python .
Runtime error R6034
- Python executable getting a runtime error. R6034
- Py2exe: the exe is created but if you run it you get a Runtime error R6034
- how to avoid runtime error R6034 with C Runtime (MSVCR) on Windows #89
제시된 방법중 Anaconda를 사용할 경우 아래와 같은 방법도 있다.
PyThreadState_Get: no current thread
아래와 같은 에러가 출력되면서 프로그램이 종료된다.
Fatal Python error: PyThreadState_Get: no current thread
[kilojoules-20160s:64471] *** Process received signal ***
[kilojoules-20160s:64471] Signal: Abort trap: 6 (6)
[kilojoules-20160s:64471] Signal code: (0)
[kilojoules-20160s:64471] *** End of error message ***
별개의 라이브러리에서 각각 별개의 Python 구현체를 갖고있을 경우 위와 같은 현상이 발생될 수 있다. 보통 정적 라이브러리로 여러 라이브러리를 만들면 생길 수 있는 문제이다. 공유라이브러리로 바꾸면 된다.
Custom OpenSSL library
- openssl 웹서버 : 비표준 위치에 SSL을 지원하는 Python 구현
- Python SVN - py3k/Modules/Setup.dist
- (꿀팁 031) - pip가 sslError로 인해 실행되지 않는 경우, ssl 모듈이 없는 경우
여러 OpenSSL 라이브러리가 존재하여, -lssl
플래그가 원하는 경로의 SSL에 링크되지 않을 경우 아래와 같은 해결 방법이 있다.
configure.ac
와 Modules/Setup.dist
파일을 아래와 같이 수정한다.
diff -urN Python-3.7.3-ori/configure.ac Python-3.7.3/configure.ac
--- Python-3.7.3-ori/configure.ac 2019-03-26 05:21:05.000000000 +0900
+++ Python-3.7.3/configure.ac 2019-06-12 10:13:29.831577474 +0900
@@ -5612,6 +5612,14 @@
# Check for usable OpenSSL
AX_CHECK_OPENSSL([have_openssl=yes],[have_openssl=no])
+have_openssl=yes
+OPENSSL_INCLUDES="/usr/local/c2core/include"
+OPENSSL_LDFLAGS="/usr/local/c2core/lib/libssl.so /usr/local/c2core/lib/libcrypto.so"
+OPENSSL_LIBS=""
+AC_SUBST([OPENSSL_INCLUDES])
+AC_SUBST([OPENSSL_LIBS])
+AC_SUBST([OPENSSL_LDFLAGS])
+
if test "$have_openssl" = yes; then
AC_MSG_CHECKING([for X509_VERIFY_PARAM_set1_host in libssl])
diff -urN Python-3.7.3-ori/Modules/Setup.dist Python-3.7.3/Modules/Setup.dist
--- Python-3.7.3-ori/Modules/Setup.dist 2019-03-26 05:21:05.000000000 +0900
+++ Python-3.7.3/Modules/Setup.dist 2019-06-12 10:14:53.375633702 +0900
@@ -204,14 +204,14 @@
#_csv _csv.c
# Socket module helper for socket(2)
-#_socket socketmodule.c
+_socket socketmodule.c
# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
-#SSL=/usr/local/ssl
-#_ssl _ssl.c \
-# -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
-# -L$(SSL)/lib -lssl -lcrypto
+SSL=/usr/local/c2core
+_ssl _ssl.c \
+ -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
+ -L$(SSL)/lib $(SSL)/lib/libssl.so $(SSL)/lib/libcrypto.so
# The crypt module is now disabled by default because it breaks builds
# on many systems (where -lcrypt is needed), e.g. Linux (I believe).
그 후, 아래와 같이 명령을 실행하면 된다. 중요한 점은 -Wl,-rpath,$PREFIX/lib
옵션을 사용하여 공유 라이브러리를 우선 찾는 경로를 지정해야 한다.
PKG_CONFIG_PATH=$PREFIX/lib/pkgconfig \
CFLAGS="-I/opt/X11/include -I$PREFIX/include -fPIC" \
LDFLAGS="-L/opt/X11/lib -L$PREFIX/lib -Wl,-rpath,$PREFIX/lib" \
./configure --enable-shared --enable-optimizations --prefix=$PREFIX | tee $BUILD_LOG1
make -j8 install
make error: ModuleNotFoundError: Not module named '_ctypes'
소스코드로 빌드시 위와 같은 에러가 발생될 경우 libffi를 설치해 보자. Ubuntu의 경우 sudo apt-get install libffi-dev
를 사용하자.
One more word, full necessary dependencies on my Ubuntu 18.04:
sudo apt-get install build-essential libsqlite3-dev sqlite3 bzip2 libbz2-dev zlib1g-dev libssl-dev openssl libgdbm-dev libgdbm-compat-dev liblzma-dev libreadline-dev libncursesw5-dev libffi-dev uuid-dev
CERTIFICATE_VERIFY_FAILED
CERTIFICATE_VERIFY_FAILED항목 참조.
ImportError: dlopen: cannot load any more object with static TLS
해결중 ...
Can't connect to HTTPS URL because the SSL module is not available
Python 빌드시 OpenSSL와 함께 설치해야 한다.
exec 에서 typing 패키지의 NameError 발생
Python:builtins#exec 에서 typing 패키지의 NameError 발생 항목 참조.
exec 이후 coverage.py 오작동 발생
Python:builtins#exec 이후 coverage.py 오작동 발생 항목 참조.
os.getcwd() 에서 FileNotFoundError 가 발생될 경우
Python:os#FileNotFoundError in os.getcwd 항목 참조.
ModuleNotFoundError: No module named '../pydevd'
Python:ensurepip#ModuleNotFoundError in pydevd 항목 참조.
eval 실행 직후 Annotation 누실 문제
Python:Eval#Annotation 누실 문제 항목 참조.
Missing api-ms-win-core-path-l1-1.0.dll
python 3.9.x 이상 부터 Windows 7 에서 지원되지 않는듯 하다. (필요하면 직접 컴파일)
해당 DLL (api-ms-win-core-path-l1-1.0.dll) 은 Windows 10 부터 지원되는 듯 하다. (Windows 8.1 확인 필요)
object.new() takes exactly one argument
다음과 같은 에러 출력:
object.__new__()
는 type 에 대한 Argument 단 하나만 필요하다는 내용이다. 다음의 코드 부분이 문제라면:
class ModuleOpen(ModuleBase):
_opened: bool
def __new__(cls, *args, **kwargs):
instance = super().__new__(cls, *args, **kwargs)
instance._opened = False
return instance
instance = super().__new__(cls)
로 수정하면 된다.
map 결과가 zip 에서 루프되지 않음
areas = map(lambda c: contour_area(c, area_oriented), contours)
for contour, area in zip(contours, areas):
...
위의 상황에서 areas 는 map 으로 인해 생성된 Generator 이다. 이넘이 python 3.10.x (정확한 버전및 상황은 모름) 에서 루프되지 않는다. 따라서 map()
을 list(map())
처럼 list로 감싸야 한다.
See also
Favorite site
- Python website
- Wikipedia (en) Python Package Manager
- Hello world: 메일 서비스 파이썬 적용 경험
- GUI Programming in Python
- The Python Graph Gallery
- 1. 명령 줄과 환경 — 파이썬 설명서 주석판
- [추천] Awesome Python
Basic
Online Python Coding
- Python web site
- [추천] Execute Python Online (온라인 파이선 컴파일 및 실행)
- PythonTutor
- SKLPT
- PythonAnywhere
- CodeChef
Guide
- Python으로 오픈API 이용하기
- 환경변수 구하기
- GpgStudy - 파이썬 스크립트를 임베디드 한 상태에서 패키지 포함하는 방법이...?
- 번역 - 이터레이터와 제너레이터
- [추천] Python 3.7의 새로운 기능들
- 파이썬 패키지를 공유하는 법
- Python의 숨은? 특징 (어머 이건 사야 돼)
- Python의 숨은? 특징 2
- [추천] 고성능 ML 백엔드를 위한 10가지 Python 성능 최적화 팁 | Hyperconnect Tech Blog
Parsing C++
- Parsing C++ in Python with Clang
- Stackoverflow: building a parser with clang
- Using Clang to analyze legacy C++ source code
Tutorials
- [추천] 왕초보를 위한 Python 2.7
- [추천] Python Tutorials – Real Python
- Full Stack Python
- Tutorials Point
- WikiDocs - 초보자를 위한 파이썬 300제
- WikiDocs - Python 3.4 공부 좀 해볼까?
- WikiDocs - 점프 투 파이썬
- 씽크 파이썬 - 프로그래밍 포기자를 위해 고안한 독특한 강의 교재! - 문법 No! 프로그래밍 Yes!
References
-
http://docs.python.org/faq/windows.html#is-a-pyd-file-the-same-as-a-dll ↩
-
Python_underscore_-_mingrammers_note.pdf ↩