programing

PyQt 응용 프로그램에서 스레드화:Qt 스레드 또는 Python 스레드를 사용합니까?

padding 2023. 7. 27. 21:40
반응형

PyQt 응용 프로그램에서 스레드화:Qt 스레드 또는 Python 스레드를 사용합니까?

저는 웹 연결을 통해 정기적으로 데이터를 검색하는 GUI 애플리케이션을 작성하고 있습니다.이 검색에는 시간이 걸리기 때문에 검색 프로세스 중에 UI가 응답하지 않습니다(더 작은 부분으로 분할할 수 없음).이것이 제가 웹 연결을 별도의 작업자 스레드에 아웃소싱하려는 이유입니다.

[네, 알고 있습니다. 이제 두 가지 문제가 있습니다.]

어쨌든, 그 애플리케이션은 PyQt4를 사용하기 때문에, 저는 어떤 것이 더 나은 선택인지 알고 싶습니다.하거나 Python Qt를 합니다.threading모듈? 입니까?각각의 장점/단점은 무엇입니까?아니면 전혀 다른 제안이 있습니까?

편집(보상):이 경우 해결책은 Jeff Ober와 Lukáš Lalinský가 제안한 것과 같은 비차단 네트워크 요청을 사용하는 것일 수도 있지만(따라서 기본적으로 동시성 문제는 네트워킹 구현에 맡깁니다), 일반적인 질문에 대한 보다 자세한 답변은 다음과 같습니다.

Python" "PyQt4" 입니까?threading모듈)?


편집 2: 답변해 주셔서 감사합니다.비록 100% 동의는 없지만, 그 장점은 도서관의 나머지 부분과의 통합이기 때문에 실질적인 불이익을 초래하지 않기 때문에, 그 답은 "사용 Qt"라는 공감대가 널리 퍼져 있는 것 같습니다.

두 개의 스레딩 구현 중 하나를 선택하고자 하는 사람이라면 abbot이 링크하는 PyQt 메일링 목록 스레드를 포함하여 여기에 제공된 모든 답변을 읽을 것을 강력히 권장합니다.

제가 현상금에 대해 고려한 몇 가지 답변이 있었습니다. 결국 저는 매우 적절한 외부 참조를 위해 수도원장을 선택했습니다. 하지만 그것은 아슬아슬했습니다.

다시한번 감사합니다.

이것은 얼마 전에 PyQt 메일링 리스트에서 논의되었습니다.이 주제에 대한 지오반니 바호의 논평을 인용합니다.

거의 똑같습니다.주요 차이점은 QT 스레드가 Qt(비동기 신호/슬롯, 이벤트 루프 등)와 더 잘 통합된다는 것입니다.또한 Python 스레드에서 Qt를 사용할 수 없습니다(예를 들어 Qapplication.postEvent를 통해 이벤트를 메인 스레드에 게시할 수 없습니다). QT가 작동하려면 QT 스레드가 필요합니다.

일반적으로 Qt와 상호 작용하려면 QT 스레드를 사용하고, 그렇지 않으면 Python 스레드를 사용하는 것이 일반적인 경험칙일 수 있습니다.

그리고 PyQt의 작성자가 이 주제에 대해 이전에 언급한 일부 의견: "둘 다 동일한 네이티브 스레드 구현에 대한 래퍼입니다."두 구현 모두 GIL을 동일한 방식으로 사용합니다.

Python의 스레드는 더 단순하고 안전하며, I/O 기반 애플리케이션을 위한 것이므로 GIL을 우회할 수 있습니다.즉, 트위스트 소켓 또는 논블로킹 소켓/셀렉트를 사용한 논블로킹 I/O를 고려해 보셨습니까?

편집: 스레드에 대한 추가 정보

파이썬 스레드

Python의 스레드는 시스템 스레드입니다.그러나 Python은 GIL(Global Interpreter Lock)을 사용하여 인터프리터가 한 번에 특정 크기의 바이트 코드 명령만 실행하도록 합니다.다행히 Python은 입출력 작업 중에 GIL을 해제하여 스레드를 비차단 I/O 시뮬레이션에 유용하게 사용할 수 있습니다.

중요한 주의 사항:바이트 코드 명령어의 가 프로그램의 줄 수와 일치하지 않기 때문에 이는 오해의 소지가 있습니다.Python에서는 단일 할당도 원자적이지 않을 수 있으므로 GIL을 사용하더라도 원자적으로 실행해야 하는 모든 코드 블록에 대해 mutex 잠금이 필요합니다.

QT 스레드

Python은 타사 컴파일된 모듈에 제어 권한을 넘겨주면 GIL을 릴리스합니다.필요한 경우 원자성을 보장하는 것이 모듈의 책임이 됩니다.제어가 다시 전달되면 Python은 GIL을 사용합니다.이로 인해 스레드와 함께 타사 라이브러리를 사용하면 혼동을 일으킬 수 있습니다.외부 스레딩 라이브러리를 사용하는 것은 모듈 대 인터프리터의 제어 위치와 시간에 대한 불확실성을 추가하기 때문에 더욱 어렵습니다.

QT 스레드는 GIL이 해제된 상태에서 작동합니다.QT 스레드는 QT 라이브러리 코드(및 GIL을 획득하지 않는 기타 컴파일된 모듈 코드)를 동시에 실행할 수 있습니다.그러나 QT 스레드의 컨텍스트 내에서 실행되는 Python 코드는 여전히 GIL을 획득하므로 이제 코드를 잠그기 위해 두 세트의 논리를 관리해야 합니다.

결국 QT 스레드와 Python 스레드는 모두 시스템 스레드를 둘러싼 래퍼입니다.Python으로 작성되지 않은 부분(암묵적으로 GIL 사용)은 어떤 경우에도 GIL을 사용하기 때문에 Python 스레드는 조금 더 안전합니다(위의 경고가 여전히 적용됨).

비차단 I/O

스레드는 응용프로그램을 매우 복잡하게 만듭니다.특히 Python 인터프리터와 컴파일된 모듈 코드 사이의 이미 복잡한 상호 작용을 처리할 때는 더욱 그렇습니다.많은 사람들이 이벤트 기반 프로그래밍을 따르는 것이 어렵다고 생각하지만, 이벤트 기반의 비차단 I/O는 종종 스레드보다 추론하기가 훨씬 더 어렵습니다.

비동기식 I/O를 사용하면 열려 있는 각 설명자에 대해 실행 경로가 일관되고 순서대로 유지되도록 항상 보장할 수 있습니다.분명히 한 열린 채널에 의존하는 코드가 다른 열린 채널이 데이터를 반환할 때 호출될 코드 결과에 따라 추가로 결정되는 경우 수행할 작업과 같은 해결해야 할 문제가 있습니다.

이벤트 기반의 논블로킹 I/O를 위한 한 가지 좋은 솔루션은 새로운 Diesel 라이브러리입니다.현재는 리눅스로 제한되어 있지만, 매우 빠르고 우아합니다.

또한 시스템에 사용 가능한 가장 빠른 방법(컴파일 시간에 결정됨)을 사용하여 이벤트 기반 프로그래밍을 위한 기본 프레임워크를 제공하는 멋진 라이브 이벤트 라이브러리 주변의 래퍼인 파이 이벤트를 배우는 것도 시간 가치가 있습니다.

QThreadQt 라이브러리의 나머지 부분과 통합되어 있습니다.실행되는지 하려면 즉, Qt의스메인는실행스되는드서간스레합에다객니체를이려다면동하사야해용음을드레알아드레식하를며드야▁in▁that▁between,-를 .QThread또 다른 유용한 기능은 스레드에서 자체 이벤트 루프를 실행하는 것입니다.

서버에 해야 합니다.QNetworkAccessManager.

는 제가 파이톡에서 일할 때 같은 질문을 했습니다.

에는 Qt 사용경다사합니다용야해음을우는하를 .QThreadQt 프레임워크, 특히 신호/슬롯 시스템을 사용할 수 있습니다.

신호/슬롯 엔진을 사용하면 스레드에서 다른 스레드로 프로젝트의 모든 부분과 대화할 수 있습니다.

게다가, 둘 다 C++ 바인딩이기 때문에 이 선택에 대한 성능 문제는 별로 없습니다.

PyQt와 스레드에 대한 저의 경험입니다.

는 당신이 다니권합장을을 사용하는 을 권장합니다.QThread.

제프는 좋은 점이 몇 가지 있습니다.하나의 기본 스레드만 모든 GUI 업데이트를 수행할 수 있습니다.스레드 내에서 GUI를 업데이트해야 하는 경우 Qt-4의 대기 중인 연결 신호를 사용하면 스레드 간에 데이터를 쉽게 전송할 수 있으며 QThread를 사용하는 경우 자동으로 호출됩니다. 매개 변수를 추가하는 것은 쉽지만 Python 스레드를 사용하는 경우 이러한 신호가 실행될지는 모르겠습니다.connect().

저도 추천할 수는 없지만, CPython과 Qt 스레드의 차이점을 설명해 볼 수 있습니다.

우선, Cython 스레드는 동시에 실행되지 않으며, 적어도 Python 코드는 실행되지 않습니다.예, 각 Python 스레드에 대해 시스템 스레드를 생성하지만 Global Interpreter Lock을 현재 보유하고 있는 스레드만 실행할 수 있습니다(C 확장자 및 FFI 코드는 이를 우회할 수 있지만 스레드가 GIL을 보유하지 않는 동안 Python 바이트 코드는 실행되지 않습니다).

반면에 기본적으로 시스템 스레드에 공통적인 계층인 Qt 스레드는 Global Interpreter Lock이 없으므로 동시에 실행할 수 있습니다.PyQt가 어떻게 처리하는지는 잘 모르겠지만, 당신의 Qt 스레드가 Python 코드를 호출하지 않는 한, 그들은 동시에 실행될 수 있어야 합니다(다양한 구조에서 구현될 수 있는 다양한 추가 잠금을 차단합니다).

추가 미세 조정을 위해,GIL의 소유권을 전환하기 전에 해석되는 바이트코드 명령어의 양을 수정할 수 있습니다. 값이 낮을수록 컨텍스트 전환(및 응답성이 높아질 수 있음)은 더 높지만 개별 스레드당 성능은 더 낮습니다. (콘텍스트 스위치는 비용이 많이 듭니다. 명령어 몇 개를 전환하려고 하면 속도에 도움이 되지 않습니다.)

당신의 문제에 도움이 되길 바랍니다 :)

Python과 PyQt 스레드의 정확한 차이점에 대해서는 언급할 수 없지만, 저는 당신이 하려고 하는 것을 사용하고 있습니다.QThread,QNetworkAcessManager그리고 꼭 전화하는 것.QApplication.processEvents()실이 살아 있는 동안에GUI 응답성이 정말로 해결하려는 문제라면, 후자가 도움이 될 것입니다.

언급URL : https://stackoverflow.com/questions/1595649/threading-in-a-pyqt-application-use-qt-threads-or-python-threads

반응형