MEP27: 백엔드에서 pyplot 분리 #

상태 번호

진전

브랜치 및 풀 리퀘스트 #

주요 PR(GTK3 포함):

백엔드 특정 분기 차이점:

초록 #

이 MEP는 백엔드를 리팩터링하여 보다 구조화되고 일관된 API를 제공하여 일반 코드를 제거하고 기존 코드를 통합합니다. 이를 위해 분할을 제안합니다.

  1. FigureManagerBase파생 클래스를 핵심 기능 클래스 FigureManager와 백엔드 특정 클래스 WindowBase

  2. ShowBase및 그 파생 클래스는 Gcf.show_allMainLoopBase.

자세한 설명 #

이 MEP는 백엔드 API를 하나의 단일 API로 통합하여 백엔드에서 일반 코드( _pylab_helpers및 포함 Gcf)를 제거하고 코드를 matplotlib에서 보다 적절한 수준으로 푸시하는 것을 목표로 합니다. 이를 통해 때때로 캔버스를 설정하고 다른 경우에는 백엔드에 따라 전체 창을 지정된 크기로 설정하는 것과 같이 백엔드에 나타나는 불일치를 자동으로 제거합니다 .FigureManagerBase.resize(w, h)

FigureManagerBase일반 코드의 두 가지 주요 위치는 및 에서 파생된 클래스에 나타납니다 ShowBase.

  1. FigureManagerBase현재 세 가지 직업이 있습니다.

    1. 문서는 그것을 pyplot 모드의 도우미 클래스로 설명하고 모든 것을 깔끔한 번들로 묶습니다.

    2. 그러나 캔버스와 도구 모음을 래핑할 뿐만 아니라 창 작업 자체도 모두 수행합니다. 이 두 작업의 결합은 다음 줄에서 가장 잘 보입니다. 이것은 백엔드 특정 코드 를 matplotlib 일반 코드와 결합합니다 .self.set_window_title("Figure %d" % num)self.set_window_title(title)title = "Figure %d" % num

    3. 현재 백엔드 특정 하위 클래스는 FigureManager 메인 루프를 종료할 시기를 결정합니다. 그림이 다른 그림을 제어할 수 없어야 하므로 이것은 또한 매우 잘못된 것 같습니다.

  2. ShowBase두 가지 직업이 있습니다.

    1. 그것은 등록된 모든 피규어 매니저를 훑어 _pylab_helpers.Gcf보고 그들에게 자신을 보여달라고 말하는 일을 합니다.

    2. mainloop두 번째로 메인 프로그램을 차단하여 수치가 죽지 않도록 하는 특정 백엔드를 수행하는 작업이 있습니다.

구현 #

이 MEP에 대한 설명은 대부분의 솔루션을 제공합니다.

  1. FigureManagerBase다른 백엔드 클래스와 함께 이 새 클래스를 간단히 래핑하도록 허용하지 않고 윈도우 측면을 제거합니다 . WindowBase에 대한 통과 메서드(:arrow_right:)를 사용하여 이 기능을 처리할 수 있는 새 클래스를 만듭니다 WindowBase. WindowBase서브클래싱하는 클래스 는 이전 버전과의 호환성을 보장하기 위해 GUI 특정 창 클래스도 서브 클래싱 해야 합니다( ).manager.window == manager.window

  2. 루프의 끝도 캡슐화하는 ShowBaseinto 의 메인 루프를 리팩터링합니다 . MainLoopBase우리는 exit 메서드를 잠금 해제하는 키로 인스턴스를 제공합니다 MainLoop( FigureManager루프가 종료되기 전에 모든 키가 반환되어야 함). 이렇게 하면 여러 백엔드가 동시에 실행될 가능성이 열립니다.

  3. 이제 FigureManagerBase백엔드 세부 사항이 없으므로 이름을 로 바꾸고 다음 FigureManager을 나타내는 새 파일로 이동 backend_managers.py합니다.

    1. FigureManagerBase 이를 통해 기존 클래스와 해당 종속성을 그대로 유지할 수 있으므로 백엔드를 별도의 PR로 변환할 수 있습니다.

    2. 그리고 이것은 또한 새로운 NavigationBase것이 백엔드 독립으로 변형된 MEP22를 예상 ToolManager합니다.

FigureManagerBase(캔버스, 숫자)

FigureManager(그림, 숫자)

WindowBase(title)

메모

보여 주다

보여 주다

파괴하다

모든 구성 요소에 대해 destroy를 호출합니다.

파괴하다

full_screen_toggle

로직 처리

set_fullscreen

크기 조정

크기 조정

키 누름

키 누름

get_window_title

get_window_title

set_window_title

set_window_title

_get_toolbar

FigureManagerBase의 모든 하위 클래스에 대한 공통 메서드

set_default_size

add_element_to_window

쇼베이스

MainLoopBase

메모

메인루프

시작하다

하위 클래스의 인스턴스가 더 이상 존재하지 않으면 자동으로 호출됩니다.

__전화__

메서드가 Gcf.show_all로 이동됨

향후 호환성 #

MEP 22에 대해 논의할 때 위에서 언급하지 않은 것처럼 이 리팩터를 통해 새로운 일반 기능을 쉽게 추가할 수 있습니다. 현재 MEP 22는 FigureManagerBase. 이 코드를 사용하면 단일 FigureManager 클래스에서만 작성하면 됩니다. 이것은 또한 이후의 지원 중단을 매우 간단하게 만들고 단일 클래스 NavigationToolbar2만 건드리면 됩니다.FigureManager

MEP 23은 이 리팩터링된 코드가 매우 유용한 또 다른 사용 사례를 만듭니다.

이전 버전과의 호환성 #

모든 백엔드 코드를 그대로 두고 기존 클래스에 누락된 메서드만 추가하므로 모든 사용 사례에서 원활하게 작동해야 합니다. FigureManager.resize유일한 차이점은 API의 표준화로 인해 창이 아닌 캔버스 크기를 조정 하는 데 사용되는 백엔드에 있습니다.

나는 이 리팩터링에 의해 더 이상 사용되지 않는 클래스가 더 이상 사용되지 않고 같은 시간표에서 제거될 것이라고 생각합니다. 또한 생성자 NavigationToolbar2에 대한 호출 서명의 변경 사항에 유의하십시오. FigureCanvasWx다른 모든 것과 동일한 방식으로 제거됩니다.

백엔드

매니저.리사이즈(w,h)

추가의

gtk3

창문

Tk

캔버스

Qt

창문

Wx

캔버스

FigureManagerWx는 framewindow에 대한 별칭으로 있었으므로 BC도 깨집니다.

대안 #

동일한 문제를 해결하기 위한 대체 솔루션이 있는 경우 선택한 접근 방식에 대한 정당성과 함께 여기에서 논의해야 합니다.

질문 #

Mdehoon: 여러 백엔드를 동시에 실행하는 방법에 대해 자세히 설명해 주시겠습니까?

OceanWolf: @mdehoon, 내가 말했듯이 이 MEP를 위한 것은 아니지만 이 MEP가 미래의 가능성으로 열어준다고 봅니다. 기본적으로 MainLoopBase 클래스는 백엔드 Gcf당 역할을 하며, 이 MEP에서는 백엔드당 열린 그림 수를 추적하고 해당 백엔드에 대한 메인 루프를 관리합니다. 해당 백엔드에 대해 열려 있는 수치가 없음을 감지하면 백엔드 특정 메인 루프를 닫습니다. 이 때문에 약간의 조정만으로 전체 다중 백엔드 matplotlib를 수행할 수 있다고 생각합니다. 왜 그렇게 하고 싶은지는 아직 모르지만 MainLoopBase에 가능성을 남겨둡니다. 모든 백엔드 코드 세부 사항이 리팩터링 FigureManager되어 이를 지원하므로 한 명의 관리자가 모든 백엔드를 관리합니다.

Mdehoon: @OceanWolf, 알겠습니다. 설명 감사합니다. 백엔드에 대한 균일한 API를 갖는 것은 matplotlib의 유지 관리에 매우 중요합니다. 저는 이 MEP가 올바른 방향으로 나아가는 단계라고 생각합니다.