Journal Réduire la taille des exécutables générés avec PyInstaller

Posté par  (site web personnel) . Licence CC By‑SA.
26
15
oct.
2018

En ce moment, je travaille à sortir un petit logiciel libre écrit en Python et PyQt. Le bébé est là: https://github.com/bluebird75/sxtool

Il permet de manipuler les fichiers s19, s28 et s37. Ce sont des images binaires dans un format texte. Ce type d'image est utilisé dans l'embarqué pour charger du code binaire. Il arrive parfois qu'on ait envie après la génération dudit fichier de changer une valeur, de modifier une adresse, etc. Comme chaque ligne a un checksum, c'est parfois un peu fastidieux et c'est pour ça qu'un petit outil est pratique.

Le soft est développé et pratiquement prêt à sortir. Comme je veux qu'il soit facile à installer, je vais en faire une version "packagée" pour Windows, c'est à dire un zip qui contient un .exe et deux-trois exemples. C'est nettement plus pratique à utiliser que d'installer Python et PyQt. Pour Linux, je me contenterai d'une installation par pip ou setup.py . En tout cas, pour Windows, j'utilise donc un "Python freezer", en occurrence PyInstaller version 3.4 .

Je lance le bouzin et il me génère un beau répertoire avec un exécutable. Super !

Sauf qu'il y deux-trois autres trucs avec:

$ sort -n du.out
36      ./sxtool/PyQt5/Qt/plugins/iconengines
56      ./sxtool/PyQt5/Qt/plugins/platformthemes
136     ./sxtool/PyQt5/Qt/plugins/styles
1352    ./sxtool/PyQt5/Qt/plugins/imageformats
3221    ./sxtool/PyQt5/Qt/translations
3484    ./sxtool/PyQt5/Qt/plugins/platforms
5068    ./sxtool/PyQt5/Qt/plugins
26989   ./sxtool/PyQt5/Qt/bin
35278   ./sxtool/PyQt5/Qt
44810   ./sxtool/PyQt5
86710   .
86710   ./sxtool

$ find . | wc
    128     128    3856

86 MOctets pour 128 fichiers ! C'est énorme !

On en parlait justement il y a quelques jours, plus ça va, plus les applications prennent de la place pour pas grand chose. Je ne serai pas celui qui livre une appli de la taille de Windows 95 juste pour éditer 3 lignes de fichier texte !

Voyons déjà ce que ça donne en détail. Merci au passage à git de fournir du, sort, uniq, find et wc sous Windows qui me permettent d'obtenir cette belle petite liste de taille en kilo-octet (les lignes blanches sont ajoutées par moi pour un groupement plus logique):

    1504    ./sxtool/sxtool.exe
    4       ./sxtool/sxtool.exe.manifest
    5780    ./sxtool/Qt5Core.dll
    428     ./sxtool/Qt5DBus.dll
    6192    ./sxtool/Qt5Gui.dll
    1232    ./sxtool/Qt5Network.dll
    3348    ./sxtool/Qt5Qml.dll
    3548    ./sxtool/Qt5Quick.dll
    324     ./sxtool/Qt5Svg.dll
    148     ./sxtool/Qt5WebSockets.dll
    5412    ./sxtool/Qt5Widgets.dll

    60      ./sxtool/python3.dll
    3756    ./sxtool/python37.dll
    2428    ./sxtool/libcrypto-1_1-x64.dll
    2452    ./sxtool/libGLESv2.dll
    520     ./sxtool/libssl-1_1-x64.dll
    972     ./sxtool/ucrtbase.dll
    660     ./sxtool/MSVCP140.dll
    88      ./sxtool/VCRUNTIME140.dll
    4       ./sxtool/api-ms-win-core-console-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-datetime-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-debug-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-errorhandling-l1-1-0.dll
    8       ./sxtool/api-ms-win-core-file-l1-1-0.dll
    12      ./sxtool/api-ms-win-core-file-l1-2-0.dll
    12      ./sxtool/api-ms-win-core-file-l2-1-0.dll
    4       ./sxtool/api-ms-win-core-handle-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-heap-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-interlocked-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-libraryloader-l1-1-0.dll
    16      ./sxtool/api-ms-win-core-localization-l1-2-0.dll
    4       ./sxtool/api-ms-win-core-memory-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-namedpipe-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-processenvironment-l1-1-0.dll
    8       ./sxtool/api-ms-win-core-processthreads-l1-1-0.dll
    12      ./sxtool/api-ms-win-core-processthreads-l1-1-1.dll
    4       ./sxtool/api-ms-win-core-profile-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-rtlsupport-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-string-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-synch-l1-1-0.dll
    12      ./sxtool/api-ms-win-core-synch-l1-2-0.dll
    4       ./sxtool/api-ms-win-core-sysinfo-l1-1-0.dll
    12      ./sxtool/api-ms-win-core-timezone-l1-1-0.dll
    4       ./sxtool/api-ms-win-core-util-l1-1-0.dll
    16      ./sxtool/api-ms-win-crt-conio-l1-1-0.dll
    16      ./sxtool/api-ms-win-crt-convert-l1-1-0.dll
    12      ./sxtool/api-ms-win-crt-environment-l1-1-0.dll
    16      ./sxtool/api-ms-win-crt-filesystem-l1-1-0.dll
    16      ./sxtool/api-ms-win-crt-heap-l1-1-0.dll
    12      ./sxtool/api-ms-win-crt-locale-l1-1-0.dll
    24      ./sxtool/api-ms-win-crt-math-l1-1-0.dll
    20      ./sxtool/api-ms-win-crt-multibyte-l1-1-0.dll
    16      ./sxtool/api-ms-win-crt-process-l1-1-0.dll
    16      ./sxtool/api-ms-win-crt-runtime-l1-1-0.dll
    20      ./sxtool/api-ms-win-crt-stdio-l1-1-0.dll
    20      ./sxtool/api-ms-win-crt-string-l1-1-0.dll
    16      ./sxtool/api-ms-win-crt-time-l1-1-0.dll
    12      ./sxtool/api-ms-win-crt-utility-l1-1-0.dll

    28      ./sxtool/select.pyd
    1052    ./sxtool/unicodedata.pyd
    88      ./sxtool/_bz2.pyd
    40      ./sxtool/_hashlib.pyd
    252     ./sxtool/_lzma.pyd
    76      ./sxtool/_socket.pyd
    124     ./sxtool/_ssl.pyd
    196     ./sxtool/pyexpat.pyd

    768     ./sxtool/base_library.zip

    2208    ./sxtool/PyQt5/QtCore.pyd
    2292    ./sxtool/PyQt5/QtGui.pyd
    4924    ./sxtool/PyQt5/QtWidgets.pyd
    108     ./sxtool/PyQt5/sip.pyd

    26989   ./sxtool/PyQt5/Qt/bin
    4080    ./sxtool/PyQt5/Qt/bin/d3dcompiler_47.dll
    16      ./sxtool/PyQt5/Qt/bin/libEGL.dll
    2452    ./sxtool/PyQt5/Qt/bin/libGLESv2.dll
    20436   ./sxtool/PyQt5/Qt/bin/opengl32sw.dll
    1       ./sxtool/PyQt5/Qt/bin/qt.conf

    36      ./sxtool/PyQt5/Qt/plugins/iconengines
    36      ./sxtool/PyQt5/Qt/plugins/iconengines/qsvgicon.dll

    1352    ./sxtool/PyQt5/Qt/plugins/imageformats
    32      ./sxtool/PyQt5/Qt/plugins/imageformats/qgif.dll
    40      ./sxtool/PyQt5/Qt/plugins/imageformats/qicns.dll
    32      ./sxtool/PyQt5/Qt/plugins/imageformats/qico.dll
    324     ./sxtool/PyQt5/Qt/plugins/imageformats/qjpeg.dll
    28      ./sxtool/PyQt5/Qt/plugins/imageformats/qsvg.dll
    28      ./sxtool/PyQt5/Qt/plugins/imageformats/qtga.dll
    364     ./sxtool/PyQt5/Qt/plugins/imageformats/qtiff.dll
    24      ./sxtool/PyQt5/Qt/plugins/imageformats/qwbmp.dll
    476     ./sxtool/PyQt5/Qt/plugins/imageformats/qwebp.dll

    3484    ./sxtool/PyQt5/Qt/plugins/platforms
    816     ./sxtool/PyQt5/Qt/plugins/platforms/qminimal.dll
    724     ./sxtool/PyQt5/Qt/plugins/platforms/qoffscreen.dll
    548     ./sxtool/PyQt5/Qt/plugins/platforms/qwebgl.dll
    1396    ./sxtool/PyQt5/Qt/plugins/platforms/qwindows.dll

    56      ./sxtool/PyQt5/Qt/plugins/platformthemes
    56      ./sxtool/PyQt5/Qt/plugins/platformthemes/qflatpak.dll

    136     ./sxtool/PyQt5/Qt/plugins/styles
    136     ./sxtool/PyQt5/Qt/plugins/styles/qwindowsvistastyle.dll

    3221    ./sxtool/PyQt5/Qt/translations
    160     ./sxtool/PyQt5/Qt/translations/qtbase_ar.qm
    164     ./sxtool/PyQt5/Qt/translations/qtbase_bg.qm
    176     ./sxtool/PyQt5/Qt/translations/qtbase_ca.qm
    172     ./sxtool/PyQt5/Qt/translations/qtbase_cs.qm
    172     ./sxtool/PyQt5/Qt/translations/qtbase_da.qm
    192     ./sxtool/PyQt5/Qt/translations/qtbase_de.qm
    1       ./sxtool/PyQt5/Qt/translations/qtbase_en.qm
    164     ./sxtool/PyQt5/Qt/translations/qtbase_es.qm
    176     ./sxtool/PyQt5/Qt/translations/qtbase_fi.qm
    164     ./sxtool/PyQt5/Qt/translations/qtbase_fr.qm
    188     ./sxtool/PyQt5/Qt/translations/qtbase_gd.qm
    136     ./sxtool/PyQt5/Qt/translations/qtbase_he.qm
    160     ./sxtool/PyQt5/Qt/translations/qtbase_hu.qm
    160     ./sxtool/PyQt5/Qt/translations/qtbase_it.qm
    128     ./sxtool/PyQt5/Qt/translations/qtbase_ja.qm
    132     ./sxtool/PyQt5/Qt/translations/qtbase_ko.qm
    152     ./sxtool/PyQt5/Qt/translations/qtbase_lv.qm
    160     ./sxtool/PyQt5/Qt/translations/qtbase_pl.qm
    176     ./sxtool/PyQt5/Qt/translations/qtbase_ru.qm
    124     ./sxtool/PyQt5/Qt/translations/qtbase_sk.qm
    156     ./sxtool/PyQt5/Qt/translations/qtbase_uk.qm

    86710   ./sxtool
    86711   .

Bon, il y a du pain sur la planche.

Mon logiciel ne fait que des trucs très basiques : ouvrir un fichier texte, appliquer des opérations dessus et le sauver. Ah, et il utilise un système de config en xml (pardon, c'est pas moi qui l'ai codé). Et côté Qt, il utilise quelques widgets classiques: fenêtre, dialogues, vue sur une table. Pas de traduction, pas de plugin, pas d'icônes, pas d'images, pas de conversion, pas de 3D.

Commençons par les trucs faciles: les modules Qt. Je n'utilise que Qt5Core, Qt5Widgets et Qt5Gui. PyInstaller l'a d'ailleurs bien compris car il n'embarque que QtCore.pyd, QtGui.pyd et QtGui.pyd. Par contre, il livre quand même l'ensemble des DLL de Qt. Exit donc: Qt5dbus.dll Qt5Network.dll Qt5Qml.dll Qt5Quick.dll Qt5Svg.dll Qt5WebSockets.dll .

Qt tire aussi pas mal de fichiers de configs et plugins. Regardons de plus prêt: PyQt5/Qt/translations a l'air de contenir plein de traductions dont je ne me sers a priori pas du tout. Mon appli est en anglais dans un Windows français donc si ça doit merdouiller, j'imagine que je le verrai tout de suite. Allez, on vire … et ça continue à marcher. Ouf.

J'avoue que je fais un peu dans l'expérimental. Si j'arrive à lancer mon appli, c'est que elle a tout ce dont elle a besoin et ça valide mes choix. On verra un autre jour pour la théorie.

Je n'utilise pas d'images ni d'icônes, et encore moins de SVG. Exit Qt/plugins/imageformats et iconengines . Je vérifie des fois que Qt l'utilise en interne mais non, ça passe nickel.

C'est quoi ce répertoire PyQt5/Qt/bin . Je suis sur que j'ai pas besoin de lancer un autre exécutable. En fait, ça contient des dll et un fichier de conf: opengl32sw.dll d3dcompiler_47.dll libGLESv2.dll libEGL.dll et qt.conf. Tout ça ressemble à des DLL dont auraient besoin des outils qui seraient dans bin. C'est pas mon cas, on dégage. Et sxtool se lance toujours, ça roule.

C'est quoi ce platformthemes/qflatpak.dll ? Ca m'a tout l'air d'être un thème de rendu pour flatpak sous Gnome. Ca sert à rien sous Windows, non ? En plus, Qt a souvent des mode de secours pour quand il ne trouve pas ses plugins. Donc je suis pas inquiet, sxtool pourra s'en passer.

Du côté de plugins/platforms/, je vais être plus prudent. Si j'en crois la documentation ça implémente des services fondamentaux de Qt sur une plate-forme donnée. C'est utilisé en embarqué pour définir par exemple les modules d'affichage (x11, wayland, framebuffer, etc). Si j'ai bien compris la documentation, je n'ai besoin que de l'un d'entre eux, celui de Windows, ou même d'aucuns si Qt a prévu quelque chose par défaut.

Vérification faite, si je vire platforms/qwindows.dll , mon application ne se lance plus. Mais je peux virer tous les autres sans impact visible: qminimal.dll qwebgl.dll qoffscreen.dll .

Il me reste un candidat à virer: PyQt5/Qt/plugins/styles/qwindowsvistastyle.dll . Mais là, je doute un peu. Le style Vista permet peut-être à mon application de ne pas ressembler à un windows 95 quand on la lance sur un autre ordinateur ? Je préfère le garder pour l'instant…

Pour Qt, j'ai bien nettoyé. Résultat des courses:

    $ du .
    1396    ./PyQt5/Qt/plugins/platforms
    136     ./PyQt5/Qt/plugins/styles
    1536    ./PyQt5/Qt/plugins
    1536    ./PyQt5/Qt
    11068   ./PyQt5
    43940   .

50%, c'est déjà un beau chiffre!

Passons à Python. Je vois pas mal de .pyd qui trainent à côté de sxtool.exe . A ma connaissance, je ne fais pas de compression, pas de hashage, pas de socket, pas de ssl et pas d'exploration de unicode. Exit donc: _bz2.pyd _hashlib.pyd _lzma.pyd _socket.pyd _ssl.pyd select.pyd unicodedata.pyd.

Je lance, ça marche toujours. Ouf.

Il y a quelques DLL qui me semblent inutiles: libssl, libcrypto, libGLESv2.dll, étaient probablement liées à ce que j'ai déjà viré. Exit aussi.

Il reste les trucs Microsoft: VCRUNTIME140.dll MSVCP140.dll. C'est des runtimes qui sont demandés lors de l'utilisation avec Qt. Mais ça sert vraiment à quelque chose ? Sur ma machine, je les vire et ça continue à marcher très bien. J'en profite pour virer aussi tous les api-ms-win-core-*.dll api-ms-win-crt-*.dll et ça marche encore.

J'avoue que je fais de l'expérimental là. Il me semble que ce type de fichier peut servir lorsqu'on exécute dans un PC moins fourni en DLL existantes. Peut-être que ça ne marchera plus chez Mme Michou. En attendant Mme Michou, je suis content que ça fonctionne encore chez moi et je ferai plus de test sur d'autres PC non windows 7 si j'en trouve.

Voyons où j'en suis:

    $ du .
    [...]
    34768   .

Pas mal !

Bilan de cette première passe, j'ai enlevé plein de fichiers et tout ceux qui restent sont indispensable pour mon application. Mais quand même, tout ça me semble encore bien gros. Si je veux gratter encore, il va me falloir réduire la taille des fichiers qui sont listés. Un très bon candidat se présente sous le forme de: base_library.zip . Il s'agit des modules de la lib standard de Python dont PyInstaller a estimé que j'avais besoin. Il ne représente que 768k sur les 34Mo mais il a l'avantage est qu'il est très facile à modifier puisque c'est un zip.

Regardons ce qu'il a dans le ventre (merci 7zip au passage):

    $ "c:\Program Files\7-Zip\7z.exe" l sxtool\base_library.zip

    7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

    Scanning the drive for archives:
    1 file, 784782 bytes (767 KiB)

    Listing archive: sxtool\base_library.zip

    --
    Path = sxtool\base_library.zip
    Type = zip
    Physical Size = 784782

       Date      Time    Attr         Size   Compressed  Name
    ------------------- ----- ------------ ------------  ------------------------
    1980-01-01 00:00:00 .....         1272         1272  _bootlocale.pyc
    1980-01-01 00:00:00 .....        15226        15226  sre_compile.pyc
    1980-01-01 00:00:00 .....         5373         5373  reprlib.pyc
    1980-01-01 00:00:00 .....         7485         7485  _weakrefset.pyc
    1980-01-01 00:00:00 .....         1484         1484  encodings\iso2022_kr.pyc
    1980-01-01 00:00:00 .....         2486         2486  encodings\cp1257.pyc
    1980-01-01 00:00:00 .....         2496         2496  encodings\iso8859_6.pyc
    1980-01-01 00:00:00 .....         8188         8188  encodings\cp737.pyc
    1980-01-01 00:00:00 .....         4539         4539  encodings\utf_8_sig.pyc
    1980-01-01 00:00:00 .....         2459         2459  encodings\iso8859_7.pyc
    1980-01-01 00:00:00 .....         1469         1469  encodings\cp950.pyc
    1980-01-01 00:00:00 .....         2466         2466  encodings\quopri_codec.pyc
    1980-01-01 00:00:00 .....         1469         1469  encodings\johab.pyc
    1980-01-01 00:00:00 .....         1657         1657  encodings\utf_16_be.pyc
    1980-01-01 00:00:00 .....         2452         2452  encodings\iso8859_5.pyc
    1980-01-01 00:00:00 .....         7497         7497  encodings\cp858.pyc
    1980-01-01 00:00:00 .....         3970         3970  encodings\__init__.pyc
    1980-01-01 00:00:00 .....         1706         1706  encodings\cp65001.pyc
    1980-01-01 00:00:00 .....         2479         2479  encodings\cp1250.pyc
    1980-01-01 00:00:00 .....         1484         1484  encodings\iso2022_jp.pyc
    1980-01-01 00:00:00 .....         1488         1488  encodings\iso2022_jp_3.pyc
    1980-01-01 00:00:00 .....         1471         1471  encodings\euc_kr.pyc
    1980-01-01 00:00:00 .....         2550         2550  encodings\iso8859_11.pyc
    1980-01-01 00:00:00 .....         1718         1718  encodings\mbcs.pyc
    1980-01-01 00:00:00 .....         3308         3308  encodings\bz2_codec.pyc
    1980-01-01 00:00:00 .....         6319         6319  encodings\aliases.pyc
    1980-01-01 00:00:00 .....         2492         2492  encodings\cp1253.pyc
    1980-01-01 00:00:00 .....         2459         2459  encodings\iso8859_13.pyc
    1980-01-01 00:00:00 .....         1487         1487  encodings\shift_jisx0213.pyc
    1980-01-01 00:00:00 .....         2456         2456  encodings\iso8859_15.pyc
    1980-01-01 00:00:00 .....         1531         1531  encodings\oem.pyc
    1980-01-01 00:00:00 .....         1483         1483  encodings\euc_jisx0213.pyc
    1980-01-01 00:00:00 .....         2484         2484  encodings\cp1258.pyc
    1980-01-01 00:00:00 .....         2433         2433  encodings\hex_codec.pyc
    1980-01-01 00:00:00 .....         1488         1488  encodings\iso2022_jp_1.pyc
    1980-01-01 00:00:00 .....         1772         1772  encodings\unicode_escape.pyc
    1980-01-01 00:00:00 .....         2472         2472  encodings\mac_greek.pyc
    1980-01-01 00:00:00 .....         2499         2499  encodings\mac_romanian.pyc
    1980-01-01 00:00:00 .....         1471         1471  encodings\gb2312.pyc
    1980-01-01 00:00:00 .....         8049         8049  encodings\cp862.pyc
    1980-01-01 00:00:00 .....         7760         7760  encodings\mac_arabic.pyc
    1980-01-01 00:00:00 .....         4856         4856  encodings\utf_16.pyc
    1980-01-01 00:00:00 .....         1494         1494  encodings\iso2022_jp_2004.pyc
    1980-01-01 00:00:00 .....         1483         1483  encodings\euc_jis_2004.pyc
    1980-01-01 00:00:00 .....         2514         2514  encodings\cp856.pyc
    1980-01-01 00:00:00 .....         1477         1477  encodings\shift_jis.pyc
    1980-01-01 00:00:00 .....         2442         2442  encodings\cp1140.pyc
    1980-01-01 00:00:00 .....         1477         1477  encodings\big5hkscs.pyc
    1980-01-01 00:00:00 .....         1473         1473  encodings\gb18030.pyc
    1980-01-01 00:00:00 .....         1465         1465  encodings\gbk.pyc
    1980-01-01 00:00:00 .....         2482         2482  encodings\cp424.pyc
    1980-01-01 00:00:00 .....         1782         1782  encodings\unicode_internal.pyc
    1980-01-01 00:00:00 .....         8149         8149  encodings\cp1125.pyc
    1980-01-01 00:00:00 .....         2451         2451  encodings\iso8859_1.pyc
    1980-01-01 00:00:00 .....         2438         2438  encodings\cp273.pyc
    1980-01-01 00:00:00 .....         2490         2490  encodings\iso8859_8.pyc
    1980-01-01 00:00:00 .....         1487         1487  encodings\shift_jis_2004.pyc
    1980-01-01 00:00:00 .....         1657         1657  encodings\utf_16_le.pyc
    1980-01-01 00:00:00 .....         7860         7860  encodings\cp863.pyc
    1980-01-01 00:00:00 .....         6440         6440  encodings\punycode.pyc
    1980-01-01 00:00:00 .....         2477         2477  encodings\iso8859_14.pyc
    1980-01-01 00:00:00 .....         2458         2458  encodings\iso8859_16.pyc
    1980-01-01 00:00:00 .....         2488         2488  encodings\mac_cyrillic.pyc
    1980-01-01 00:00:00 .....         2466         2466  encodings\kz1048.pyc
    1980-01-01 00:00:00 .....         1488         1488  encodings\iso2022_jp_2.pyc
    1980-01-01 00:00:00 .....         7860         7860  encodings\cp865.pyc
    1980-01-01 00:00:00 .....         8193         8193  encodings\cp866.pyc
    1980-01-01 00:00:00 .....         2503         2503  encodings\koi8_r.pyc
    1980-01-01 00:00:00 .....         8157         8157  encodings\cp855.pyc
    1980-01-01 00:00:00 .....         2960         2960  encodings\charmap.pyc
    1980-01-01 00:00:00 .....         3248         3248  encodings\uu_codec.pyc
    1980-01-01 00:00:00 .....         1469         1469  encodings\cp932.pyc
    1980-01-01 00:00:00 .....         2528         2528  encodings\cp1006.pyc
    1980-01-01 00:00:00 .....         2451         2451  encodings\iso8859_2.pyc
    1980-01-01 00:00:00 .....         7860         7860  encodings\cp861.pyc
    1980-01-01 00:00:00 .....         7904         7904  encodings\cp852.pyc
    1980-01-01 00:00:00 .....         5747         5747  encodings\idna.pyc
    1980-01-01 00:00:00 .....         3052         3052  encodings\rot_13.pyc
    1980-01-01 00:00:00 .....         7896         7896  encodings\cp775.pyc
    1980-01-01 00:00:00 .....         2478         2478  encodings\cp1256.pyc
    1980-01-01 00:00:00 .....         2541         2541  encodings\tis_620.pyc
    1980-01-01 00:00:00 .....         2186         2186  encodings\undefined.pyc
    1980-01-01 00:00:00 .....         2452         2452  encodings\cp500.pyc
    1980-01-01 00:00:00 .....         1469         1469  encodings\cp949.pyc
    1980-01-01 00:00:00 .....         7509         7509  encodings\cp857.pyc
    1980-01-01 00:00:00 .....         1792         1792  encodings\raw_unicode_escape.pyc
    1980-01-01 00:00:00 .....         2549         2549  encodings\cp720.pyc
    1980-01-01 00:00:00 .....         1467         1467  encodings\big5.pyc
    1980-01-01 00:00:00 .....         2451         2451  encodings\iso8859_4.pyc
    1980-01-01 00:00:00 .....         7866         7866  encodings\cp437.pyc
    1980-01-01 00:00:00 .....         2491         2491  encodings\mac_iceland.pyc
    1980-01-01 00:00:00 .....         2489         2489  encodings\mac_roman.pyc
    1980-01-01 00:00:00 .....         2490         2490  encodings\mac_centeuro.pyc
    1980-01-01 00:00:00 .....         2481         2481  encodings\cp1254.pyc
    1980-01-01 00:00:00 .....         2456         2456  encodings\cp1026.pyc
    1980-01-01 00:00:00 .....         1471         1471  encodings\euc_jp.pyc
    1980-01-01 00:00:00 .....         7886         7886  encodings\cp869.pyc
    1980-01-01 00:00:00 .....         1919         1919  encodings\latin_1.pyc
    1980-01-01 00:00:00 .....         2479         2479  encodings\cp1252.pyc
    1980-01-01 00:00:00 .....         2446         2446  encodings\base64_codec.pyc
    1980-01-01 00:00:00 .....         1492         1492  encodings\iso2022_jp_ext.pyc
    1980-01-01 00:00:00 .....         2500         2500  encodings\cp1255.pyc
    1980-01-01 00:00:00 .....         2632         2632  encodings\mac_latin2.pyc
    1980-01-01 00:00:00 .....         1550         1550  encodings\utf_32_be.pyc
    1980-01-01 00:00:00 .....         2456         2456  encodings\iso8859_10.pyc
    1980-01-01 00:00:00 .....         2451         2451  encodings\iso8859_9.pyc
    1980-01-01 00:00:00 .....         3146         3146  encodings\zlib_codec.pyc
    1980-01-01 00:00:00 .....         2479         2479  encodings\palmos.pyc
    1980-01-01 00:00:00 .....         4749         4749  encodings\utf_32.pyc
    1980-01-01 00:00:00 .....         2414         2414  encodings\koi8_t.pyc
    1980-01-01 00:00:00 .....         1907         1907  encodings\ascii.pyc
    1980-01-01 00:00:00 .....         2449         2449  encodings\cp875.pyc
    1980-01-01 00:00:00 .....         7527         7527  encodings\cp850.pyc
    1980-01-01 00:00:00 .....         2580         2580  encodings\cp874.pyc
    1980-01-01 00:00:00 .....         2573         2573  encodings\ptcp154.pyc
    1980-01-01 00:00:00 .....         1637         1637  encodings\utf_8.pyc
    1980-01-01 00:00:00 .....         2452         2452  encodings\cp037.pyc
    1980-01-01 00:00:00 .....         2498         2498  encodings\mac_croatian.pyc
    1980-01-01 00:00:00 .....         8006         8006  encodings\cp864.pyc
    1980-01-01 00:00:00 .....         1550         1550  encodings\utf_32_le.pyc
    1980-01-01 00:00:00 .....         7845         7845  encodings\cp860.pyc
    1980-01-01 00:00:00 .....         2489         2489  encodings\koi8_u.pyc
    1980-01-01 00:00:00 .....         1463         1463  encodings\hz.pyc
    1980-01-01 00:00:00 .....         2653         2653  encodings\hp_roman8.pyc
    1980-01-01 00:00:00 .....         2476         2476  encodings\cp1251.pyc
    1980-01-01 00:00:00 .....         1578         1578  encodings\utf_7.pyc
    1980-01-01 00:00:00 .....         2492         2492  encodings\mac_turkish.pyc
    1980-01-01 00:00:00 .....         2432         2432  encodings\mac_farsi.pyc
    1980-01-01 00:00:00 .....         2458         2458  encodings\iso8859_3.pyc
    1980-01-01 00:00:00 .....        34578        34578  locale.pyc
    1980-01-01 00:00:00 .....        13923        13923  operator.pyc
    1980-01-01 00:00:00 .....         6474         6474  abc.pyc
    1980-01-01 00:00:00 .....         4267         4267  copyreg.pyc
    1980-01-01 00:00:00 .....         6314         6314  sre_constants.pyc
    1980-01-01 00:00:00 .....        13827        13827  re.pyc
    1980-01-01 00:00:00 .....        19536        19536  traceback.pyc
    1980-01-01 00:00:00 .....        28965        28965  _collections_abc.pyc
    1980-01-01 00:00:00 .....         3432         3432  io.pyc
    1980-01-01 00:00:00 .....        19133        19133  weakref.pyc
    1980-01-01 00:00:00 .....         8997         8997  types.pyc
    1980-01-01 00:00:00 .....        21380        21380  sre_parse.pyc
    1980-01-01 00:00:00 .....        14385        14385  heapq.pyc
    1980-01-01 00:00:00 .....         3812         3812  linecache.pyc
    1980-01-01 00:00:00 .....        13789        13789  warnings.pyc
    1980-01-01 00:00:00 .....        23837        23837  functools.pyc
    1980-01-01 00:00:00 .....        23770        23770  enum.pyc
    1980-01-01 00:00:00 .....          228          228  collections\abc.pyc
    1980-01-01 00:00:00 .....        46633        46633  collections\__init__.pyc
    1980-01-01 00:00:00 .....         1832         1832  keyword.pyc
    1980-01-01 00:00:00 .....        33921        33921  codecs.pyc
    ------------------- ----- ------------ ------------  ------------------------
    1980-01-01 00:00:00             767304       767304  150 files

Ce qui saute au yeux… c'est cette histoire de date. D'où on est en 1980 ? M'est avis que le zipper de PyInstaller (qui est probablement celui de Python) ne conserve pas les dates de modification des fichiers par défaut.

Ensuite, il y a beaucoup de fichier décrivant des encodages. De mémoire, ces encodages sont chargés dynamiquement quand on les demande. Ce qui veut dire que je pourrais en virer quelques uns si je n'en ai pas besoin. Vérifions le fichier Python37\Lib\encodings\__init__.py:

[...]
def search_function(encoding):

    # Import the module:
    #
    [...]
    for modname in modnames:
        try:
            # Import is absolute to prevent the possibly malicious import of a
            # module with side-effects that is not in the 'encodings' package.
            mod = __import__('encodings.' + modname, fromlist=_import_tail,
                             level=0)

C'est bien ce que je pensais. Quand on réclame un encodage, le module correspondant est importé à la demande. Donc, je peux ne garder que ceux dont j'ai besoin.

A coup d'essai, erreur et répétition, je peux faire fonctionner mon application en ne gardant que:

1980-01-01 00:00:00 .....         6319         6319  encodings\aliases.pyc
1980-01-01 00:00:00 .....         1907         1907  encodings\ascii.pyc
1980-01-01 00:00:00 .....         1919         1919  encodings\latin_1.pyc
1980-01-01 00:00:00 .....         1792         1792  encodings\raw_unicode_escape.pyc
1980-01-01 00:00:00 .....         1772         1772  encodings\unicode_escape.pyc
1980-01-01 00:00:00 .....         1782         1782  encodings\unicode_internal.pyc
1980-01-01 00:00:00 .....         1637         1637  encodings\utf_8.pyc
1980-01-01 00:00:00 .....         4539         4539  encodings\utf_8_sig.pyc
1980-01-01 00:00:00 .....         3970         3970  encodings\__init__.pyc

Ca me parait assez raisonnable. Ce sont les encodages standard les plus utilisés. Par contre, je ne sais pas si mon application pourra lire un fichier sur un Windows configuré en Japonais… On verra. Au pire, ces japonisants pourront utiliser l'installation par pip qui embarque bien tout ce qu'il faut… ou bien me faire un bug report et je remettrai tout ça.

    $ "C:\Program Files\7-Zip\7z.exe" d base_library.zip -r base64_codec.pyc big5.pyc big5hkscs.pyc bz2_codec.pyc charmap.pyc cp*.pyc euc_*.pyc gb*.pyc hex_codec.pyc hp_roman8.pyc hz.pyc idna .pyc iso*.pyc johab.pyc koi8_*.pyc kz1048.pyc mac_*.pyc mbcs.pyc oem.pyc palmos.pyc ptcp154.pyc punycode.pyc quopri_codec.pyc rot_13.py  shift_jis*.pyc tis_620.pyc undefined.pyc utf_7.pyc utf_1*.pyc utf_3*.pyc uu_codec.pyc zlib_codec.pyc

    7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30
    Open archive: base_library.zip

    Path = base_library.zip
    Type = zip
    Physical Size = 784782
    Updating archive: base_library.zip

    Delete data from archive: 116 files, 369278 bytes (361 KiB)
    Keep old data in archive: 34 files, 398026 bytes (389 KiB)
    Add new data to archive: 0 files, 0 bytes

    Files read from disk: 0
    Archive size: 401682 bytes (393 KiB)
    Everything is Ok

Je suis donc passé de 784 koctets à 400 koctets. C'est toujours ça de pris.

Pour les autres modules Python, ils sont pas très nombreux. En interne, je n'utilise que: functools io optparse os sys traceback unittest xml.dom.minidom xml.sax Tous les autres modules sont des dépendances internes de la machinerie Python. Je fais quand même le test, je vire un .pyc au hasard. De fait, mon appli ne se lance plus.

Alors, où en est-on niveau taille ?

    $ du  -a
    396     ./sxtool/base_library.zip
    196     ./sxtool/pyexpat.pyd
    1396    ./sxtool/PyQt5/Qt/plugins/platforms/qwindows.dll
    1396    ./sxtool/PyQt5/Qt/plugins/platforms
    136     ./sxtool/PyQt5/Qt/plugins/styles/qwindowsvistastyle.dll
    136     ./sxtool/PyQt5/Qt/plugins/styles
    1536    ./sxtool/PyQt5/Qt/plugins
    1536    ./sxtool/PyQt5/Qt
    2208    ./sxtool/PyQt5/QtCore.pyd
    2292    ./sxtool/PyQt5/QtGui.pyd
    4924    ./sxtool/PyQt5/QtWidgets.pyd
    108     ./sxtool/PyQt5/sip.pyd
    11068   ./sxtool/PyQt5
    60      ./sxtool/python3.dll
    3756    ./sxtool/python37.dll
    5780    ./sxtool/Qt5Core.dll
    6192    ./sxtool/Qt5Gui.dll
    5412    ./sxtool/Qt5Widgets.dll
    1504    ./sxtool/sxtool.exe
    4       ./sxtool/sxtool.exe.manifest
    34396   ./sxtool

Et une fois compressé, ça donne:

    10260   ./sxtool-1.1.zip

Ça nous fait donc 10 MOctets à télécharger, et 34 Moctets une fois installé. Ca reste trop à mon goût mais je commence à manquer d'idées facile à mettre en place.

Ce qui prend beaucoup de place, c'est clairement les DLL Qt et les bindings Qt en pyd. Pour les DLL Qt, il y a surement moyen de faire mieux. Ces DLLs provienennt de l'installation par défaut de PyQt, qui doivent embarquer un Qt configuré avec un maximum d'options. Surement qu'en le recompilant
à la mano et en virant toutes les options, ça doit être plus petit. J'avoue que j'ai un peu la flemme pour aujourd'hui.

L'étape d'après serait de voir s'il est possible dans un module Qt de ne pas tout embarquer. C'est une petit application, je n'utilise que très peu de Qt:

QtCore:

  • Qt, pyqtSignal, QFont, QRegExpValidator, QMetaObject, QRegExp, QCoreApplication, QSize, QRect

QtWidgets:

  • QAbstractItemView, QAction, QActionGroup, qApp, QApplication, QCheckBox, QComboBox, QDialog, QDialogButtonBox, QFileDialog, QGridLayout
  • QGroupBox, QHBoxLayout, QHeaderView, QInputDialog, QLabel, QLineEdit, QMainWindow, QMenu, QMenuBar, QMessageBox, QPushButton, QRadioButton
  • QSizePolicy, QSpinBox, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget

QtGui:

  • QFont, QRegExpValidator

Si je pouvais configurer Qt et PyQt pour n'embarquer que ces modules là et leurs dépendances, je suis sur que je passerai sous les 10 Moctets. Il y a quand même 203 classes dans QtWidgets et j'en utilise 29. Maintenant que c'est dit, j'ai jamais entendu parlé d'un outil ou tutorial qui ferait ça. Et ça doit pas être aussi simple que ça en a l'air.

Je vais m'arrêter là pour aujourd'hui. Mon bilan de réduction est de 60% moyennant environ 2h de boulot. Je suis content, mais si je suppute que je vais devoir remettre les runtime MSVP4 et les autres lib.

Ca fait réfléchir quand même.

Je me souviens d'une époque lointaine où quand on lançait Py2exe, on passait ensuite deux jours à rajouter une par une toutes les DLLs nécessaires et on se prenait la tête à coup de dlldepend. Il fallait quand même être un power-developer. Et encore, c'était déjà une grosse simplification de l'usage par rapport a cx_freeze. PyInstaller fait clairement bien le boulot aujoud'hui puisque cette étape n'est plus nécessaire. La vie du développeur est simplifiée, mais est-ce qu'elle n'est pas devenue trop simple ? Ca veut dire qu'un développeur qui n'a pas envie de se prendre la tête comme je l'ai fait va livrer les 86 Moctets de binaire. Donc 60% de trucs inutiles. J'aimerai bien jeter un coup d'œil de prêt au clavier Android pour voir si on est dans la même situation…

  • # go

    Posté par  (site web personnel) . Évalué à -3.

    Le langage go a justement été fait pour cela. Le programme final est compilé en statique. Aucune dépendance du coup, pas de merdier associé…

    • [^] # Re: go

      Posté par  (site web personnel) . Évalué à 2.

      Malheureusement ce n'est pas aussi simple: dans le cas présent la majeure partie des dépendances en trop sont dues à Qt, dans le cas d'un programme en Go on aurait donc eu un binding vers les lib dynamiques intégré dans le binaire.

    • [^] # Re: go

      Posté par  (site web personnel) . Évalué à 3.

      Go n'a presque pas de dépendance. Le binaire de base fait quand même 7 Mo (runtime).

      "La première sécurité est la liberté"

      • [^] # Re: go

        Posté par  (site web personnel) . Évalué à 10.

        En même temps, Go fait quand même beaucoup moins de choses que Qt… C'est plus facile d'être compact.

    • [^] # Re: go

      Posté par  . Évalué à 6.

      Pour un programme compilé (pas PyQt alors), il est aussi possible de "linker" Qt en statique, et alors s'opère le grand ménage dans les fonctions…
      On peut arriver à des résultats très compacts (exemple en embarqué: 7Mo non compressé).

      • [^] # Re: go

        Posté par  (site web personnel) . Évalué à 1.

        C'est très intéressant !

        Par contre Ça ne pose pas de soucis avec la license de Qt ?

        Autre question: ne serait-ce pas possible d'utiliser le configurateur de Qt pour désactiver tout ce qui n'est pas utile à un projet donner, puis d'utiliser les .so générés à la place de ceux fournis par défaut par PyQt ?

        • [^] # Re: go

          Posté par  (site web personnel) . Évalué à 3.

          Pour la deuxième partie, c'est tout à fait possible, c'est ce dont je parle à la fin du journal. J'essaierai de faire un test dans ce sens un de ces quatre et de vous faire un retour.

  • # J'ai testé tes modifs

    Posté par  (site web personnel) . Évalué à 6.

    Le programme se lance parfaitement mais au bout d'un moment le clavier se blo

  • # Quel usage de Qt

    Posté par  (site web personnel) . Évalué à 3.

    Si c'est pour l'interface graphique et qu'elle reste pas trop grosse (compliquée), tu aurais peut-être intérêt à retirer complètement la dépendance à Qt et à faire un petit truc en Tkinter (en utilisant ttk pour avoir des widgets ok). Sous Windows c'est livré avec l'installeur Python, tu n'aurais plus qu'à livrer ton script en .pyw et hop.

    Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

    • [^] # Re: Quel usage de Qt

      Posté par  . Évalué à 6. Dernière modification le 15 octobre 2018 à 20:40.

      Sous Windows c'est livré avec l'installeur Python, tu n'aurais plus qu'à livrer ton script en .pyw et hop

      Euh comment dire… As tu deja essaye de faire installer un python a un utilsateur lambda de windows? Essaye tu vas voir c'est … interessant comme experience et tu comprendras que ton idee de pyw c'est une tres tres mauvaise idee… surtout si il y a une seule dependance a autre chose que les libs par defaut.

      • [^] # Re: Quel usage de Qt

        Posté par  . Évalué à 3.

        Un personne "lambda" qui veut éditer du S37 n'aura peut-être pas peur du python (la réciproque n'étant pas vraie : quelqu'un qui veut éditer du python face au S37… ?)

        • [^] # Re: Quel usage de Qt

          Posté par  . Évalué à 6.

          Tu serais setonne de ce que des gens tres competents dans leur domaine sont incapable de faire des qu'il est question de terminal…

      • [^] # Re: Quel usage de Qt

        Posté par  (site web personnel) . Évalué à 1.

        Au pire, il repasse par l'étape de freeze pour refaire un exécutable complet, mais sans embarquer la partie Qt. Après, ça fait embarquer Tcl+Tk, je ne sais pas quel volume ça occupe.

        Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

      • [^] # Re: Quel usage de Qt

        Posté par  . Évalué à -5.

        Euh comment dire… As tu deja essaye de faire installer un python a un utilsateur lambda de windows?

        C'est marrant, je viens de le faire il y a moins de 5 min…

        choco install python2 -y

        • [^] # Re: Quel usage de Qt

          Posté par  . Évalué à 7.

          Et chocolatey c'est la meme personne qui l'a installe? Et tu appelles une personne capable de se servir du terminal un utilisateur windows lambda?

          On doit pas connaitre les memes utilisateurs…

          • [^] # Re: Quel usage de Qt

            Posté par  . Évalué à -1.

            la démonstration fonctionne un user lambda, surement bon dans son domaine (qui sais utiliser un terminal en tout cas), qui installe une version de python non compatible avec celle du développeur qui à clairement exprimé utiliser python 3.7
            :)

  • # UPX

    Posté par  . Évalué à 3.

    Ça marche vachement bien pour les binaires : https://github.com/upx/upx
    C'est plus lent au lancement, donc pas très intéressant pour les outils simples, et ça prend de la mémoire. Mais ça a l'air de coller à ton cas.

    Par contre, il semblerait que pour Windows 10, ça deviennent difficile : https://github.com/upx/upx/issues/154#issuecomment-368741687

    Maintenant, à toi de voir.

  • # Qt static

    Posté par  (site web personnel) . Évalué à 1.

    Je profite de ton sujet pour me plaindre également car je suis un grand fan de Qt, en langage noble C++ par contre, mais sa taille dynamique me fait sérieusement réfléchir … Je ne comprends pas pourquoi Qt ne livre pas des librairies statiques, de cette façon on n'embarque que le nécessaire.

    Et avec du QML c'est pire. On se moque des applis Électron mais bon Qt n'est pas mieux.

    • [^] # Re: Qt static

      Posté par  . Évalué à 2.

      Il me semble que tu compiler Qt en statique, mais pas la version communautaire… il faut payer.

      • [^] # Re: Qt static

        Posté par  (site web personnel) . Évalué à 4.

        Il est tout a fait possible de compiler Qt en statique avec la version « Communautaire ».

        Qt est LGPL ça veux dire aucun problème si ton appli est libre (ce qui devrait être le cas, on est sur linuxfr après tout). Et même si ton appli est proprio, la LGPL le permet à condition que tu permettes à l'utilisateur de customiser Qt (ce qui peut être possible en fournissant les .o)

    • [^] # Re: Qt static

      Posté par  . Évalué à 0.

      En fait, c'est déjà un problème purement Windowsien…
      Sur un système digne de ce non, Qt est installé au niveau système, il n'a pas a venir avec chaque exécutable.
      Dans ce cas il faut justement éviter le linkage statique, en effet; pour la première application qui se lance et qui utilise Qt, les librairies sont chargées en mémoire, les suivantes se lance rapidement car elle ne font que les ré-utiliser…

      Dans un système KDE par exemple; l'ensemble des applications graphique est écrit en Qt, même le gestionnaire de fenêtre; et un système sous KDE reste bien bien plus petit que le dossier C:\Windows de la plupart de vos PC.

      C'est sur que si Qt est utilisé que pour un tout petit logiciel, c'est overkill, mais si on l'exploite au niveau système, c'est tout de suite plus intéressant.

      Après, Windows n'aide pas pour cette façon de concevoir et distribuer les applications… D'ailleurs, c'est le même problème pour Python… Sous Gnu/Linux, un script python sans trop de dépendance s’exécute sur presque toutes les distributions qu'il soit Python2 ou Python3. Sous Windows, c'est un autre problème…
      Après reste que sous Linux, packager et distribuer une application reste compliqué, mais bon, la perfection n'existe nul part aujourd'hui.

      Pour en revenir a Qt, il faut aussi se dire que ce n'est pas le seul framework graphique C++; c'est pas pour rien que Samsung a basé son OS Tizen sur les EFL; alors qu'il héritait de Meego, qui lui était 100% Qt; il ont fait ce choix pour la très petite embarqué (je ne parle pas des monstres de smartphone d'aujourd'hui qui n'ont rien de vraiment embarqué, mais surtout des montres connecté de la marque), la, EFL, c'est tout aussi jolie, beaucoup beaucoup plus léger (en RAM surtout), par contre, c'est moins sexy/facile a coder que du Qt/QML…

      • [^] # Re: Qt static

        Posté par  . Évalué à 1.

        Windows c'est tout de meme un systeme ou, au moins sous windows 7, le driver de la carte wifi prenait plus de 1 Giga… Ok ok je sais que c'est plus la faute de Intel (le fabricant) mais tout de meme.

      • [^] # Re: Qt static

        Posté par  (site web personnel) . Évalué à 3. Dernière modification le 16 octobre 2018 à 10:20.

        je ne parle pas des monstres de smartphone d'aujourd'hui qui n'ont rien de vraiment embarqué, mais surtout des montres connecté de la marque

        Un système embarqué par définition n'est pas lié à de faibles ressources. Ce n'est qu'une des définitions possibles.

        Un ordinateur classique qui sert de terminal de retrait d'argent liquide est par exemple un système embarqué. Alors que le système est puissant et basé sur une architecture PC.

        Le fait que le téléphone portable n'ait pas de clavier / souris, que la batterie est un élément important du système et que l'intégration des composants doit être optimale définie un téléphone même surpuissant comme un système embarqué aussi.

        • [^] # Re: Qt static

          Posté par  . Évalué à 2.

          Certe; mais dans ces cas, les problèmes de place utilisé, de ram, de cpu nécessaire, sont tout de suite moins importants, du coup, le choix entre utiliser un truc facile comme Qt (qui peut être lourd, mais qui se code / maintient facilement) vis a vis des EFL (qui est certe plus léger est efficace, mais plus complexe a utiliser, et limite aussi le nombre de développeur d'application potentiel car Qt est quand même plus largement utilisé) ne justifie pas d'exclure Qt.

          Sur une montre, la taille et les problème de dissipation thermique oblige un peu d'utiliser un petit CPU, peu de RAM; et surtout, comme la batterie est petite, et qu'on attend en générale une autonomie la plus importante possible sur ces produits, l'optimisation énergétique est un point important. Et la EFL possède aussi des arguments en or…

      • [^] # Re: Qt static

        Posté par  (site web personnel) . Évalué à 2.

        Après, Windows n'aide pas pour cette façon de concevoir et distribuer les applications…

        le problème est bien windows et l'écosystème qu'il promeut, pas les développeurs pour une fois :-)

      • [^] # Re: Qt static

        Posté par  . Évalué à 1.

        Sur un système digne de ce non, Qt est installé au niveau système, il n'a pas a venir avec chaque exécutable.
        Dans ce cas il faut justement éviter le linkage statique, en effet; pour la première application qui se lance et qui utilise Qt, les librairies sont chargées en mémoire, les suivantes se lance rapidement car elle ne font que les ré-utiliser…

        Que le monde est beau ! Les oiseaux chantent ! Les méchants sont habillés en noir, les gentils en blanc,…

        Ce que tu dis est tellement proche de la réalité que l'on a pas de problème de packaging sous linux. Donc pas de guerre des gestionnaires de paquet, on a pas besoin des snap/appimage/flatpak, docker n'existe pas,…

        Ou alors ce n'est pas si simple ?

    • [^] # Re: Qt static

      Posté par  (site web personnel) . Évalué à 2.

      On se moque des applis Électron mais bon Qt n'est pas mieux.

      Une application python packagée avec Qt peut faire 34Mo (d'après l'auteur du journal), alors qu'une application Electron fait minimum 120 Mo.

      Donc Qt est ~4x mieux.

    • [^] # Re: Qt static

      Posté par  (site web personnel) . Évalué à 4. Dernière modification le 18 octobre 2018 à 12:13.

      Étant développeur Qt professionnellement, je me sens obligé de répondre. Qt est un grand framework, c'est vrai mais il est finement bien découpé.

      Par contre, moi je fais du C++ donc je ne sais pas comment cela fonctionne avec Python.

      Voici mon code d'exemple.

      #include <QApplication>
      #include <QLabel>
      
      int main(int argc, char** argv)
      {
              QApplication app(argc, argv);
              QLabel label("Hello World");
      
              label.show();
      
              return app.exec();
      }

      Le test se fait sur Linux, donc forcément profitant des bibliothèques partagées c'est pas très pertinent. Cela dit, vu qu'on parle de Qt, on va quand même mesurer la taille si on devait importer les bibliothèques.

      Évidemment je note pas les autres bibliothèques (wayland, GL, libX11) puisque ce serait plus ou moins identique avec un autre framework.

      • main : 16Ko (autant ne pas le compter)
      • libQt5Widgets.so : 6.7Mo
      • libQt5Gui.so : 5.2Mo
      • libQt5Core.so : 5.1Mo

      À titre de comparaison, avec Gtk on aurait ces bibliothèques à importer.

      • libgtk-3 : 7.4Mo
      • libgdk-3 : 1.1Mo
      • libglib-2.0 : 1.2Mo
      • libgio-2.0 : 1.8Mo

      Plus léger effectivement, mais Qt reste largement acceptable.

      git is great because linus did it, mercurial is better because he didn't

  • # UNIX vs MS-DOS Epoch

    Posté par  . Évalué à 2.

    Ce qui saute au yeux… c'est cette histoire de date. D'où on est en 1980 ?

    Apparemment, en établissant la liste des fichiers, 7-zip modifie les dates pour les ré-initialiser à l'heure Unix. Sous Windows, ce moment ne correspond pas à ce qu'on rencontre sur les systèmes *nix, du moins d'après ce blog. D'où les dates « 1980 » que tu as rencontrées.

  • # tkInter ?

    Posté par  (Mastodon) . Évalué à 3.

    Tu devrai te pencher sur TKInter:

    • C'est intégré dans python "de base" et sur toutes les plateformes (win, linux, OSX)
    • C'est tout petit
    • C'est tunnable à volonté (pour l'aspect graphique)

    .. et du coup, pas de packaging on un packaging minimal…

    Courage !

    • [^] # Re: tkInter ?

      Posté par  (site web personnel) . Évalué à 3. Dernière modification le 16 octobre 2018 à 20:26.

      Même si j'utilisais TkInter, je ferai le choix d'un packaging en .exe . Le packaging est un aspect fondamental de la distribution d'un programme. Dans l'univers Python, PIP est le minimum vital et tout ce qu'on peut fournir en plus participera à facilité d'installation et donc la popularité d'une programme.

      TkInter est petit certes, mais pour faire une vue à la Excel avec nombre de lignes illimitées sur le fichier de donnée, j'ai peur qu'il soit un peu court. C'est pour ça que Qt assure bien, on peut faire des applis assez haut niveau avec très peu de code.

      Je l'ai utilisé une ou deux fois contre mon gré et je ne regrette pas Qt.

      En cadeau, un snapshot de SxTool pour voir de quoi je parle.
      SxTool

  • # Windows 95 a

    Posté par  . Évalué à 7.

    Je ne serai pas celui qui livre une appli de la taille de Windows 95 juste pour éditer 3 lignes de fichier texte !

    Tu veux dire 3 fois la taille de Windows 95 : la première version prenait 33 Mo sur le disque!

    ⚓ À g'Auch TOUTE! http://afdgauch.online.fr

  • # Taille déraisonnable

    Posté par  . Évalué à 1.

    Je suis assez surpris par la taille de ton exécutable.

    J'ai fait quelques interfaces graphiques plus complexes que celle que tu nous présentes pour des besoins en interne (IDE pour automatismes, interfaces de communication pyserial)).
    J'en suis à maximum 20MB sans compter les ressources (images, programmes non liés statiquement).

    • J'ai essayé sur mon PC en win7, python3.6.4, PyQt5.9, le programme fonctionne.
    • J'ai essayé avec un .spec générique (que j'utilise): le programme fait 18 MB mais j'ai un message d'erreur "Failed to execute script tool" sans autre message, donc inutilisable, je ne comprends pas pourquoi et désolé, je ne vais pas avoir le temps de chercher…

    sxtool.spec

    # -*- mode: python -*-
    
    block_cipher = None
    
    a = Analysis(['sxtool.py'],
                 pathex=[],
                 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)
    exe = EXE(pyz,
              a.scripts,
              a.binaries,
              a.zipfiles,
              a.datas,
              name='sxtool',
              debug=False,
              strip=False,
              upx=True,
              console=False )

    genInstaller.bat

    set PATH=%PATH%;C:\Qt\Qt5.9.0\5.9\msvc2015_64\bin
    
    del /Q dist\sxtool.exe
    rmdir /S /Q __pycache__
    rmdir /S /Q dist
    rmdir /S /Q build
    
    pyinstaller sxtool.spec
    move dist\sxtool.exe .

    Je viens de m'apercevoir que j'ai un projet perso que j'avais fait à l'arrache que je peux te partager (par mail) mais pas diffuser : il y a dedans l'enregistrement des préférences, du glisser/déposer de fichier, de l'appel à un programme tiers. Par contre, dans cette interface, pas de menus, pas d'ouverture de fichier xml, et sans commentaires parce que c'est suffisamment parlant pour moi, j'avais essayé de prototyper un modèle MVC… Ce serait vraiment que pour montrer une façon de faire (très très basique) d'une interface graphique avec création d'un éxecutable et génération du fichier d'installation… Si ça t'intéresse…

    • [^] # Re: Taille déraisonnable

      Posté par  (site web personnel) . Évalué à 2.

      Je veux bien juste pour voir à quoi ça ressemble. Ecris-moi à phil.fremy (chez) free.fr .

      Merci en tout cas de regarder, je vais voir si je peux retravailler le .spec comme le tien.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.