Created
May 9, 2019 10:34
-
-
Save RavenKyu/02b5afcf4ebe2e7dd8d47e625354bab4 to your computer and use it in GitHub Desktop.
멀티프로세스 사용시 각 프로세스별 다른 파이썬 가상환경 지정 예제
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 본 예제는 v_1, v_2, v_3 이라는 파이썬 가상환경이 미리 생성되어 있어야 한다. | |
# 각 가상환경에는 다른 버전의 PyYAML 이 설치 되어 있어야 한다. | |
import multiprocessing as mp | |
import os, sys | |
import pathlib | |
from functools import wraps | |
def info(title, version): | |
import site | |
msg = 'title: {title}\t' \ | |
'sys_executable: {executable}\t' \ | |
'process id: {proc_id}\t' \ | |
'site-package: {site_package}\t' \ | |
'Package Version: {version}' | |
print(msg.format(title=title, executable=sys.executable, | |
proc_id=os.getpid(), version=version, | |
site_package=site.getsitepackages())) | |
def deco(f): | |
# 멀티프로세싱에서 데코레이터를 사용하기 위해서 functools.wraps를 사용 | |
@wraps(f) | |
def active_virtualenv(*args, **kwargs): | |
exec_path = sys.executable | |
# 패스 설정 | |
old_os_path = os.environ.get('PATH', '') | |
os.environ['PATH'] = os.path.dirname( | |
os.path.abspath(exec_path)) + os.pathsep + old_os_path | |
base = os.path.dirname(os.path.dirname(os.path.abspath(exec_path))) | |
# 플랫폼에 따른 site-packages 위치 | |
if sys.platform == 'win32': | |
site_packages = os.path.join(base, 'Lib', 'site-packages') | |
else: | |
site_packages = os.path.join(base, 'lib', | |
'python%s' % sys.version[:3], | |
'site-packages') | |
# site-package 추가 | |
prev_sys_path = list(sys.path) | |
import site | |
site.addsitedir(site_packages) | |
sys.real_prefix = sys.prefix | |
sys.prefix = base | |
new_sys_path = [] | |
# 패스 우선순위 변경 | |
for item in list(sys.path): | |
if item not in prev_sys_path: | |
new_sys_path.append(item) | |
sys.path.remove(item) | |
sys.path[:0] = new_sys_path | |
# 실제 함수 실행 | |
f(*args, **kwargs) | |
return active_virtualenv | |
# 실제 사용하게 될 함수 | |
@deco | |
def func(name): | |
import yaml | |
info(name, yaml.__version__) | |
if __name__ == '__main__': | |
# spawm | |
# 부모 프로세스는 깨끗한 새 파이썬 인터프리터 프로세스를 시작합니다. | |
# 자식 프로세스는 프로세스 객체의 run() 메서드를 실행하는데 필요한 자원만 | |
# 상속받습니다. 특히, 부모 프로세스의 불필요한 파일 기술자와 핸들은 상속되지 | |
# 않습니다. 이 방법을 사용하여 프로세스를 시작하는 것은 fork 나 forkserver 를 | |
# 사용하는 것에 비해 다소 느립니다. | |
# 유닉스 및 윈도우에서 사용 가능합니다. 윈도우의 기본값. | |
mp.set_start_method('spawn') | |
info("main", None) | |
# 자식 프로세스를 시작할 때 사용할 파이썬 인터프리터의 경로를 설정합니다. | |
# (기본적으로 sys.executable 이 사용됩니다). | |
# 자식 프로세스를 만들기 전에 해야 합니다. | |
# 버전 3.4으로 변경: 이제 'spawn' 시작 방법을 사용할 때 유닉스에서 지원됩니다. | |
mp.set_executable(pathlib.Path( | |
"/Users/limdeokyu/Tests/Multiprocessing/venvs/v_1/bin/python")) | |
# daemon | |
# 프로세스의 데몬 플래그, 논리값. start() 가 호출되기 전에 설정되어야 합니다. | |
# 초깃값은 생성 프로세스에서 상속됩니다. | |
# 프로세스가 종료할 때, 모든 데몬 자식 프로세스를 강제 | |
# 종료시키려고(terminate) 시도합니다. | |
# 데몬 프로세스는 하위 프로세스를 만들 수 없음에 유의하십시오. | |
# 그렇지 않으면 부모 프로세스가 종료될 때 데몬 프로세스가 강제 종료되어, | |
# 데몬 프로세스가 자식 프로세스를 고아로 남기게 됩니다. | |
# 또한, 이들은 유닉스 데몬이나 서비스가 아닙니다, | |
# 데몬이 아닌 프로세스들이 종료되면 강제 종료되는 (그리고 조인되지 않는) | |
# 일반 프로세스입니다. | |
v_1 = mp.Process(target=func, args=('v_1',)) | |
v_1.start() | |
mp.set_executable(pathlib.Path( | |
"/Users/limdeokyu/Tests/Multiprocessing/venvs/v_2/bin/python")) | |
v_2 = mp.Process(target=func, args=('v_2',)) | |
v_2.start() | |
mp.set_executable(pathlib.Path( | |
"/Users/limdeokyu/Tests/Multiprocessing/venvs/v_3/bin/python")) | |
v_3 = mp.Process(target=func, args=('v_3',)) | |
v_3.start() | |
v_1.join() | |
v_2.join() | |
v_3.join() | |
info("main", None) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment