PyInstaller + PyQt 지원 아이콘

입문


Python을 사용하여 작은 GUI 프로그램을 만들 때 PyQt를 사용하여 PyInstaller를 exe로 포장합니다.
이때 좋아하는 응용 프로그램도 아이콘을 붙이고 싶어서 그 방법을 총괄한다.
대응하고 싶은 아이콘은 다음과 같은 두 가지를 나타낸다.
  • 브라우저에 표시된exe 파일 아이콘
  • 제목 표시줄 또는 작업 표시줄에 표시된 아이콘
  • 개발 환경


    이번에 확인한 환경은 다음과 같다.
  • Windows10 Pro
  • Python 3.6.4
  • PyInstaller 3.3.1
  • PyQt5 5.10.1
  • 설치


    PyInstaller 및 PyQt는 pip 에서 설치할 수 있습니다.
    > pip install pyinstaller pyqt5
    

    exe 파일 아이콘


    PyInstaller로 포장할 때 아이콘을 추가할 수 있습니다.
    > pyinstaller foo.py --onefile --noconsole --icon=bar.ico
    
    --icon ico 파일을 선택합니다.
    또한 아이콘 표시와 직접적인 관계가 없지만 --onefile 옵션으로 압축할 때 하나의 파일로 정리하고 --noconsole 옵션으로 시작할 때 컨트롤러 화면을 표시하지 않도록 지정합니다.

    제목 표시줄 또는 작업 표시줄에 표시된 아이콘


    이것은 PyQt 코드입니다. QApplication setWindowIcon() 에서 이미지 파일을 전달하면 작업 표시줄에 아이콘이 표시됩니다.
    from PyQt5.QtGui import QIcon
    from PyQt5.QtWidgets import QApplication, QWidget
    
    app = QApplication(sys.argv)
    app.setWindowIcon(QIcon('bar.ico')) # pngファイルなどでもOK
    w = QWidget()
    w.show()
    sys.exit(app.exec())
    
    따라서 bar는 PyInstaller에서 생성한 exe 파일의 경로와 같습니다.ico를 놓으면 제목 표시줄과 작업 표시줄에 아이콘이 표시됩니다.
    그러나 이렇게 되면exe파일 이외에 ico파일을 동시에 나눠줘야 하기 때문에 조금만 더 노력합시다.

    이미지 파일 포함


    PyInstaller로 압축할 때 외부 파일을 삽입할 수 있습니다. 삽입하려면 스펙 파일에 기술하십시오. 스펙 파일은 처음부터 기술할 수 있습니다.위에서 설명한 바와 같이 파일foo.py을 지정하고 PyInstaller를 이동하면 파일foo.spec을 생성합니다. 이를 바탕으로 다음 줄을 추적하면 간단합니다.
    a = Analysis(['foo.py'],
                 pathex=['C:\\work\\Python\\foo'],
                 binaries=[],
                 datas=[],
                 hiddenimports=[],
                 hookspath=[],
                 runtime_hooks=[],
                 excludes=[],
                 win_no_prefer_redirects=False,
                 win_private_assemblies=False,
                 cipher=block_cipher)
    pyz = PYZ(a.pure, a.zipped_data,
                 cipher=block_cipher)
    +a.datas += [('bar.ico', '.\\bar.ico', 'Data')]
    exe = EXE(pyz,
              a.scripts,
              a.binaries,
              a.zipfiles,
              a.datas,
              name='foo',
              debug=False,
              strip=False,
              upx=True,
              runtime_tmpdir=None,
              console=False , icon='bar.ico')
    
    이 스펙 파일을 사용하여 PyInstaller를 실행합니다.
    > pyinstaller foo.spec
    
    현재 bar.ico 파일은 편입되고 포장됩니다.

    불러온 파일


    PyInstaller에서 패키지된exe를 실행하면 임시 파일이 Temp 폴더에 펼쳐지고 상기 편집된 이미지 파일도 펼쳐지기 때문에 읽어들입니다.
    확장된 경로는 sys._MEIPASS 에서 얻을 수 있습니다. 다음 코드를 쓰면 PyInstaller를 사용할 때와 일반적으로Python으로 실행할 때 모두 대응할 수 있습니다.
    import os
    import sys
    
    def resource_path(relative):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative)
        return path.join(path.abspath('.'), relative)
    
    이것을 이용하여 아래의 코드를 쓰면 포장된 exe 파일만 제목 표시줄과 작업 표시줄에 아이콘을 표시할 수 있습니다.
    import os
    import sys
    
    from PyQt5.QtGui import QIcon
    from PyQt5.QtWidgets import QApplication, QWidget
    
    def resource_path(relative):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative)
        return path.join(path.abspath('.'), relative)
    
    def main():
        app = QApplication(sys.argv)
        app.setWindowIcon(QIcon(resource_path('bar.ico')))
        w = QWidget()
        w.show()
        sys.exit(app.exec())
    
    if __name__ == '__main__':
        main()
    

    좋은 웹페이지 즐겨찾기