pyqtdeploy, ou empacotamos o programa Python em exe'shnik ... da maneira mais difícil

KDPV


Certamente, todo mundo que pelo menos uma vez escreveu algo em Python pensou em como distribuir seu programa (ou até mesmo um script simples) sem dor de cabeça: sem ter que instalar o próprio intérprete, várias dependências, plataformas cruzadas, para que um arquivo -exe'shnikom (como último recurso, arquivo) e o menor tamanho possível.


: PyInstaller, cx_Freeze, py2exe, py2app, Nuitka … , PyQt? , ( ) , PyQt, PyQt pyqtdeploy. , , , . , , , — ( ). , : , , , , .


pyqtdeploy , , , , ?


. linux. , "exe'" .


, ( ). PyInstaller — , , . 170 ( , PyQt5 180 ). , , — QtCore, QtGui, QtWidgets — . --exclude-module . , --onefile , 60 , . , , ( - ) 170 .


pyqtdeploy. " PyQt… - , - PyQt Qt?" — .


pyqtdeploy? , , . ( , PyQt, ) Qt ( rcc) , C++, , //… . pyqtdeploy Python 3.5+ PyQt5. ( ):


  • exe' PyQt4 PyQt5, Python 2.7 Python 3.3+ ( Python 3.7.2);
  • ( exe') ( , — );
  • :
    • android-32;
    • android-64;
    • ios-64;
    • linux-64;
    • macos-64;
    • win-32;
    • win-64;
  • PyQt Qt , - QtCore, - .

pyqtdeploy


, Python 3.5+ PyQt5:


pip install PyQt5 pyqtdeploy

exe' :


  • Python-, (!);
  • sysroot , ;
  • "" .pdy, exe' ( Qt, PyQt, Python, );
  • exe' qmake.


: main.py — " " , mainwindow.py — , resources icon.png mainwindow.ui, Qt Designer. , :


main.py
src/
    |---__init__.py
    |---gui/
        |---mainwindow.py
        |---__init__.py
    |---resources/
        |---__init__.py
        |---images/
            |---icon.png
            |---__init__.py
        |---ui/
            |---mainwindow.ui
            |---__init__.py

sysroot ()


, , . sysroot.json ( , ). , (Python, Qt ..). pyqtdeploy API, , //whatever, pyqtdeploy. ( ):


openssl ( ) — (). , sysroot.json, :


"android|macos|win#openssl": {
    "android#source": "openssl-1.0.2r.tar.gz",
    "macos|win#source": "openssl-1.1.0j.tar.gz",

    "win#no_asm": true
}

, , : arch1|arch2|...#plugin-name. , (ios, android, macos, win, linux), — . , .


:


  • source () — ;
  • no_asm ( ) — . , PATH nasm;
  • python_source ( ) — , , OpenSSL macOS Python v3.6.4 ;

zlib ( ) — ( , , , ) ():


"ios|linux|macos|win#zlib": {
    "source": "zlib-1.2.11.tar.gz",

    "static_msvc_runtime": true
}

:


  • source () — , ;
  • static_msvc_runtime ( ) — MSVC (Windows);

qt5 () — ():


"qt5": {
    "android-32#qt_dir": "android_armv7",
    "android-64#qt_dir": "android_arm64_v8a",
    "ios#qt_dir": "ios",

    "linux|macos|win#source": "qt-everywhere-src-5.12.2.tar.xz",
    "edition": "opensource",

    "android|linux#ssl": "openssl-runtime",
    "ios#ssl": "securetransport",
    "macos|win#ssl": "openssl-linked",

    "configure_options": [
        "-opengl", "desktop", "-no-dbus", "-qt-pcre"
    ],
    "skip": [
        "qtactiveqt", "qtconnectivity", "qtdoc", "qtgamepad",
        ...
    ],

    "static_msvc_runtime": true
}

:


  • qt_dir ( , source) — Qt;
  • source ( , qt_dir) — Qt;
  • edition (, source) — 2 :
    • commercial;
    • opensource;
  • ssl — 3 :
    • openssl-linked — ( openssl);
    • securetransport — SSL, Qt (, , Apple’s Secure Transport);
    • openssl-runtime — OpenSSL, ;
  • configure_options — , Qt. , ;
  • skip — ( , top-level , ). Qt , qt — top-level . , , . , top-level ();
  • disabled_features — . configure -list-features ()
  • static_msvc_runtime ( ) — MSVC (Windows);

python () — ():


"python": {
    "build_host_from_source": false,
    "build_target_from_source": true,
    "source": "Python-3.7.2.tar.xz"
}

:


  • build_host_from_source () — true — Python , false — Python ( win32);
  • build_target_from_source () — true — Python , false — Python ( Python win32);
  • source (, Python ) — Python;
  • version (, Python) — Python;
  • dynamic_loading ( ) — true — (, C);
  • host_installation_bin_dir ( ) — Python, ( , win , — PATH);

sip () — , Python-bindings C/C++ ( ):


"sip": {
    "module_name": "PyQt5.sip",
    "source": "sip-4.19.15.tar.gz"
}

:


  • module_name () — sip-;
  • source () — sip;

pyqt5 () — ():


"pyqt5": {
    "android#disabled_features": [
        "PyQt_Desktop_OpenGL", "PyQt_Printer", "PyQt_PrintDialog",
        "PyQt_PrintPreviewDialog", "PyQt_PrintPreviewWidget"
    ],
    "android#modules": [
        "QtCore", "QtGui", "QtNetwork", "QtPrintSupport", "QtWidgets",
        "QtAndroidExtras"
    ],

    "ios#disabled_features": [
        "PyQt_Desktop_OpenGL", "PyQt_MacOSXOnly",
        ...
    ],
    "ios|macos#modules": [
        "QtCore", "QtGui", "QtNetwork", "QtPrintSupport", "QtWidgets",
        "QtMacExtras"
    ],

    "linux#modules": [
        "QtCore", "QtGui", "QtNetwork", "QtPrintSupport", "QtWidgets",
        "QtX11Extras"
    ],

    "win#disabled_features": ["PyQt_Desktop_OpenGL"],
    "win#modules": [
        "QtCore", "QtGui", "QtNetwork", "QtPrintSupport", "QtWidgets",
        "QtWinExtras"
    ],

    "source": "PyQt5_*-5.12.1.tar.gz"
}

:


  • disabled_features ( ) — . , , Qt ();
  • modules () — , ();
  • source () — PyQt;

pyqt3D, pyqtchart, pyqtdatavisualization, pyqtpurchasing, qscintilla ( ) — , PyQt. source — .


, . sysroot , . , , .


sysroot


sysroot.json :


{
    "linux#zlib": {
        "source": "zlib-1.2.11.tar.gz"
    },

    "linux#qt5": {
        "source": "qt-everywhere-src-5.12.2.tar",
        "edition": "opensource",

        "configure_options": [
            "-no-dbus", "-no-system-proxies", "-no-cups", "-no-sql-db2",
            "-no-sql-ibase", "-no-sql-mysql", "-no-sql-sqlite",
            "-no-sql-sqlite2", "-no-sql-oci", "-no-sql-odbc",
            "-no-sql-psql", "-no-sql-tds", "-no-sqlite", "-ccache",
            "-optimize-size"
        ],
        "skip": [
            "qt3d", "qtactiveqt", "qtandroidextras", "qtcanvas3d",
            "qtcharts", "qtconnectivity", "qtdatavis3d", "qtdeclarative",
            "qtdoc", "qtgamepad", "qtgraphicaleffects", "qtlocation",
            "qtmacextras", "qtmultimedia", "qtnetworkauth", "qtpurchasing",
            "qtquickcontrols", "qtquickcontrols2", "qtremoteobjects",
            "qtscript", "qtscxml", "qtsensors", "qtserialbus",
            "qtserialport", "qtspeech", "qtsvg", "qttools",
            "qttranslations", "qtvirtualkeyboard", "qtwayland",
            "qtwebchannel", "qtwebengine", "qtwebglplugin",
            "qtwebsockets", "qtwebview", "qtwinextras", "qtx11extras",
            "qtxmlpatterns"
        ],
        "disabled_features": [
            "network", "bearermanagement", "dnslookup", "dtls", "ftp",
            "http", "localserver", "networkdiskcache", "networkinterface",
            "networkproxy", "socks5", "udpsocket", "concurrent", "future",
            "cups", "printer", "printdialog", "printpreviewdialog",
            "printpreviewwidget", "sql", "sqlmodel", "testlib", "xml"
        ]
    },

    "linux#python": {
        "build_host_from_source": false,
        "build_target_from_source": true,
        "source": "Python-3.7.2.tgz",

        "dynamic_loading": true
    },

    "linux#sip": {
        "module_name": "PyQt5.sip",
        "source": "sip-4.19.15.tar.gz"
    },

    "linux#pyqt5": {
        "modules": ["QtCore", "QtGui", "QtWidgets"],
        "source": "PyQt5_*-5.12.2.tar.gz"
    }
}

? -, (, ssl, pyqt3D ). -, exe' linux ( , linux-64; , ).


, qt5 - , (, ). top-level QtBase. -optimize-size -ccache. Qt , , ( 5 ), , — ccache ( , linux), ( 5). , apt install ccache.


pyqt5 QtCore, QtGui, QtWidgets.


python dynamic_loading, C-extension.


sysroot, : zlib, Qt5, Python, sip, PyQt5 sysroot.json ( , ). :


pyqtdeploy-sysroot sysroot.json

, .


--verbose. , , . , dev-. , . , python3-dev, (, Requirements). , Qt Python ( , ).


, , , .


"" ()


, , exe'. pyqtdeploy GUI. ( .pdy ):


pyqtdeploy main.pdy

Fonte de aplicação


Application Source. :


  • Name — exe';
  • Main script file ( , Entry Point) — , ( , main.py);
  • Entry Point ( , Main script file) — , setuptools;
  • sys.path — , zip- (, Python egg), sys.path ( , , );
  • Target Python version — Python;
  • Target PyQt version — PyQt4 PyQt5 (, , PyQt, );
  • Use console — , ( Windows). ;
  • Application bundle — , bundle ( MacOS);
  • Application Package Directory — , . Scan… "" (src) main.py, , . (.. main.py src), main.py ( , Main script file).

: .py "" ( -) — .


:


  • Scan… — Application Package Directory;
  • Remove all — Application Package Directory;
  • Include all — Application Package Directory;
  • Exclude all — Application Package Directory;
  • Exclusions — , Application Package Directory. ;

qmake. qmake, ( );


Módulos PyQt


PyQt Modules. PyQt-, . , . QtCore, QtGui, QtWidgets, uic; sip .
PyQt, , ( ).


Biblioteca padrão


Standard Library. , , . - , . ( ) , ().


. - ( pip), - ( ), ImportError. . , PIL, fractions.


Python / (, ssl), . , . INCLUDEPATH (headers), LIBS — ( , ).


Outros pacotes


Other Packages. (, pypi). , Application source: , ( , site-packages virtual environment), Scan / ( PIL).


Other Extension Modules. C, exe' (; , , ).


, . . Package Lib.a, Name , — Package.Lib ( .a); LIBS , , -L/home/user1/venv/programme1/lib/python3.7/site-packages/Package -lLib ( , " ", /home/user1/venv/programme1/lib/python3.7/site-packages/Package/Lib.a).


, , -, , -, qmake ( , pyqt' ).


, , , Lib.so? — Package.Lib.so (.. , + ) exe'. , . , ImportError. , , _imaging.so, PIL'.


Locations. , . ( sysroot , main.pdy), .


exe' ()


- :


pyqtdeploy-build main.pdy
cd build-linux-64
../sysroot-linux-64/host/bin/qmake
make #nmake  win

, , — .


#1 — , ""


, exe', , PyInstaller:


if getattr(sys, 'frozen', False):
    #   exe'
else:
    #    exe'

#2 — (, .)


Qt " ", rcc exe'. . icon.png src/resources/images, " " — :/src/resources/images/icon.png. , . — Qt' . .. - :


icon = QIcon(':/src/resources/images/icon.png')

. , , :


icon_file = open(':/src/resources/images/icon.png', 'rb')
icon = icon_file.read()

, open , , .


Qt (, , , GUI Qt Designer .ui, loadUi), - :


ui_file = QtCore.QFile(':/src/resources/images/icon.png')
ui_file.open(QtCore.QIODevice.ReadOnly)
data = ui_file.readAll()
ui_file.close()
ui_file = BytesIO(bytes(data))


, exe', - ? PyQt, , , . - ( PyInstaller). — . ~40 (c -optimize-size ~35 ), - , .


Quando coletamos o Qt e o PyQt mínimos necessários, seria bom tentar criar um exe baseado neles usando PyInstaller ou cx_Freeze e analisar o tamanho, mas isso, como se costuma dizer, é outra história ...

Source: https://habr.com/ru/post/undefined/


All Articles