Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@RavenKyu
Created May 9, 2019 10:34
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RavenKyu/02b5afcf4ebe2e7dd8d47e625354bab4 to your computer and use it in GitHub Desktop.
Save RavenKyu/02b5afcf4ebe2e7dd8d47e625354bab4 to your computer and use it in GitHub Desktop.
멀티프로세스 사용시 각 프로세스별 다른 파이썬 가상환경 지정 예제
# 본 예제는 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