concurrent.interpreters — 동일한 프로세스 내의 여러 인터프리터¶
Added in version 3.14.
소스 코드: Lib/concurrent/interpreters
concurrent.interpreters 모듈은 하위 수준인 _interpreters 모듈을 기반으로 상위 수준의 인터페이스를 구축합니다.
이 모듈은 주로 인터프리터(일명 “서브 인터프리터”)를 관리하고 그 안에서 실행하는 기본 API를 제공하기 위한 목적입니다. 실행 과정은 대부분 현재 스레드에서 인터프리터로 전환한 다음 해당 실행 컨텍스트 내의 함수를 호출하는 것을 포함합니다.
For concurrency, interpreters themselves (and this module) don’t
provide much more than isolation, which on its own isn’t useful.
Actual concurrency is available separately through
threads See below
더 보기
InterpreterPoolExecutor익숙한 인터페이스 내에서 스레드와 인터프리터를 결합합니다.
- 확장 모듈 격리하기
여러 인터프리터를 지원하도록 확장 모듈을 업데이트하는 방법.
주요 세부 사항¶
더 자세히 알아보기 전에, 여러 인터프리터를 사용할 때 유의해야 할 몇 가지 세부 사항이 있습니다:
isolated, by default
암시적 스레드 없음
모든 PyPI 패키지가 아직 여러 인터프리터에서의 사용을 지원하는 것은 아닙니다.
소개¶
“인터프리터”는 사실상 파이썬 런타임의 실행 컨텍스트입니다. 이는 런타임이 프로그램을 실행하는 데 필요한 모든 상태를 포함하며, 여기에는 임포트 상태 및 내장 함수(builtins) 등이 포함됩니다. (메인 스레드만 존재하는 경우라도 각 스레드는 현재 인터프리터 외에도 현재 예외 및 바이트코드 평가 루프와 관련된 추가적인 런타임 상태를 가집니다.)
The concept and functionality of the interpreter have been a part of Python since version 2.2, but the feature was only available through the C-API and not well known, and the isolation was relatively incomplete until version 3.12.
다중 인터프리터 및 격리¶
파이썬 구현체는 동일한 프로세스 내에서 여러 인터프리터를 사용하는 것을 지원할 수 있으며, CPython은 이 기능을 지원합니다. 각 인터프리터는 사실상 다른 것들로부터 격리됩니다(신중하게 관리되는 소수의 프로세스 전역 예외 상황을 제외하고).
그러한 격리는 프로그램의 서로 다른 논리적 구성 요소 간에 강력한 분리를 제공하므로, 해당 구성 요소들이 상호작용하는 방식을 세밀하게 제어하고자 할 때 유용합니다.
참고
동일한 프로세스 내의 인터프리터는 기술적으로 서로 완벽하게 격리될 수 없습니다. 같은 프로세스 내에서는 메모리 접근에 대한 제한이 거의 없기 때문입니다. 파이썬 런타임은 격리를 위해 최선을 다하지만 확장 모듈이 이를 쉽게 위반할 수 있습니다. 따라서 서로의 데이터에 접근해서는 안 되는 보안 민감 상황에서는 여러 인터프리터를 사용하지 마십시오.
인터프리터에서 실행하기¶
다른 인터프리터에서 실행하는 것은 현재 스레드에서 해당 인터프리터로 전환한 다음 특정 함수를 호출하는 과정을 포함합니다. 런타임은 현재 인터프리터의 상태를 사용하여 해당 함수를 실행합니다. concurrent.interpreters 모듈은 인터프리터를 생성 및 관리하고, 전환 및 호출 작업을 수행하기 위한 기본 API를 제공합니다.
No other threads are automatically started for the operation.
There is a helper for that though.
There is another dedicated helper for calling the builtin
exec() in an interpreter.
인터프리터에서 exec() (또는 eval())이 호출되면, 인터프리터의 __main__ 모듈을 “globals” 네임스페이스로 사용하여 실행됩니다. 어떤 모듈과도 연관되지 않은 함수도 마찬가지입니다. 이는 명령줄에서 실행된 스크립트가 __main__ 모듈에서 실행되는 방식과 동일합니다.
동시성과 병렬성¶
앞서 언급했듯이, 인터프리터는 그 자체로 동시성을 제공하지 않습니다. 인터프리터는 엄격하게 런타임이 현재 스레드에서 사용할 격리된 실행 컨텍스트를 나타냅니다. 그러한 격리로 인해 프로세스와 유사하지만, 여전히 스레드와 같은 프로세스 내 효율성을 누릴 수 있습니다.
그럼에도 불구하고 인터프리터는 특정 형태의 동시성을 자연스럽게 지원합니다. 이러한 격리에는 강력한 부수 효과가 있습니다. 이는 async나 스레드에서 취할 수 있는 것과는 다른 접근 방식의 동시성을 가능하게 합니다. 이는 CSP 또는 액터 모델과 유사한 동시성 모델로, 개념적으로 파악하기 비교적 쉬운 모델입니다.
이 동시성 모델은 Stackless 스타일로 여러 인터프리터 사이를 오가며 단일 스레드 내에서 활용할 수 있습니다. 그러나 이 모델은 인터프리터와 여러 개의 스레드를 결합할 때 더 유용합니다. 이는 주로 새 스레드를 시작하고, 그곳에서 다른 인터프리터로 전환하여 원하는 내용을 실행하는 것을 포함합니다.
파이썬의 각 실제 스레드는 메인 스레드에서만 실행되는 경우라도 고유한 현재 실행 컨텍스트를 가집니다. 여러 스레드가 동일하거나 서로 다른 인터프리터를 사용할 수 있습니다.
높은 수준에서, 스레드와 인터프리터의 조합은 선택적으로 공유를 활성화하는(opt-in sharing) 스레드로 생각할 수 있습니다.
중요한 이점으로, 인터프리터는 충분히 격리되어 있어 GIL 을 공유하지 않으며, 이는 스레드와 여러 인터프리터를 결합하여 완전한 멀티 코어 병렬성을 가능하게 함을 의미합니다. (이것은 파이썬 3.12부터 적용되었습니다.)
인터프리터 간 통신¶
실제 상황에서 여러 인터프리터는 서로 통신할 수 있는 방법이 있을 때만 유용합니다. 이는 보통 어떤 형태의 메시지 전달을 포함하지만, 세심하게 관리되는 방식으로 데이터를 공유하는 것을 의미할 수도 있습니다.
이를 고려하여, concurrent.interpreters 모듈은 create_queue() 를 통해 사용할 수 있는 queue.Queue 구현체를 제공합니다.
참조¶
이 모듈은 다음 함수들을 정의합니다:
- concurrent.interpreters.list_all()¶
기존 인터프리터마다 하나씩 대응하는
Interpreter객체들의list를 반환합니다.
- concurrent.interpreters.get_current()¶
현재 실행 중인 인터프리터에 대한
Interpreter객체를 반환합니다.
- concurrent.interpreters.get_main()¶
메인 인터프리터에 대한
Interpreter객체를 반환합니다. 이는 런타임이 REPL 또는 명령줄에서 제공된 스크립트를 실행하기 위해 생성한 인터프리터입니다. 보통 유일하게 존재하는 경우입니다.
- concurrent.interpreters.create()¶
새로운 (유휴 상태의) 파이썬 인터프리터를 초기화하고 해당 객체에 대한
Interpreter객체를 반환합니다.
인터프리터 객체¶
- class concurrent.interpreters.Interpreter(id)¶
현재 프로세스 내의 단일 인터프리터.
일반적으로
Interpreter를 직접 호출해서는 안 됩니다. 대신create()또는 다른 모듈 함수를 사용하십시오.- id¶
(읽기 전용)
기본 인터프리터의 ID.
- whence¶
(읽기 전용)
인터프리터가 생성된 위치를 설명하는 문자열.
- is_running()¶
인터프리터가 현재 자신의
__main__모듈에서 코드를 실행 중이면True를, 그렇지 않으면False를 반환합니다.
- close()¶
인터프리터를 마무리하고 파괴합니다.
- prepare_main(ns=None, **kwargs)¶
인터프리터의
__main__모듈 내에 객체를 바인딩합니다.일부 객체는 실제로 공유되고 일부는 효율적으로 복사되지만, 대부분은
pickle을 통해 복사됩니다. “공유” 객체 를 참조하십시오.
- exec(code, /, dedent=True)¶
제공된 소스 코드를 인터프리터(현재 스레드)에서 실행합니다.
- call(callable, /, *args, **kwargs)¶
인터프리터(현재 스레드)에서 주어진 함수를 실행한 결과를 반환합니다.
- call_in_thread(callable, /, *args, **kwargs)¶
인터프리터(새 스레드)에서 주어진 함수를 실행합니다.
예외 처리¶
- exception concurrent.interpreters.InterpreterError¶
이 예외는
Exception의 서브 클래스로, 인터프리터 관련 오류가 발생할 때 발생합니다.
- exception concurrent.interpreters.InterpreterNotFoundError¶
이 예외는
InterpreterError의 서브 클래스로, 대상 인터프리터가 더 이상 존재하지 않을 때 발생합니다.
- exception concurrent.interpreters.ExecutionFailed¶
이 예외는
InterpreterError의 서브 클래스로, 실행 중인 코드가 처리되지 않은 예외를 발생시켰을 때 발생합니다.- excinfo¶
다른 인터프리터에서 발생한 예외의 기본 스냅샷입니다.
이 예외는
TypeError의 서브 클래스로, 객체를 다른 인터프리터로 전송할 수 없을 때 발생합니다.
인터프리터 간 통신¶
- class concurrent.interpreters.Queue(id)¶
queue.Queue인터페이스를 구현하는 저수준 교차 인터프리터 큐의 래퍼입니다. 기본이 되는 큐는create_queue()를 통해서만 생성할 수 있습니다.일부 객체는 실제로 공유되고 일부는 효율적으로 복사되지만, 대부분은
pickle을 통해 복사됩니다. “공유” 객체 를 참조하십시오.- id¶
(읽기 전용)
큐의 ID입니다.
- exception concurrent.interpreters.QueueEmptyError¶
이 예외는
queue.Empty의 서브 클래스로, 큐가 비어 있을 때Queue.get()및Queue.get_nowait()에서 발생합니다.
- exception concurrent.interpreters.QueueFullError¶
이 예외는
queue.Full의 서브 클래스로, 큐가 가득 찼을 때Queue.put()및Queue.put_nowait()에서 발생합니다.
기본 사용법¶
인터프리터를 생성하고 코드 실행하기:
from concurrent import interpreters
interp = interpreters.create()
# 현재 OS 스레드에서 실행.
interp.exec('print("spam!\