title: Python 3.x + PyQt5 + py2exe/pyinstaller/cx-Freeze
body: <p>I have been exploring the options for how to freeze my package that uses <a href="https://github.com/Widdershin/flask-desktop/" rel="nofollow noreferrer">flask-desktop</a>. Qt does a lot of the heavy-lifting, and as such it is a pretty big library.</p>
  
  <p>I experimented with several options to see what I could do. Python versions here indicate explicit support for each package.</p>
  
  <pre class="lang-none prettyprint-override"><code>|                 |Python 3.4|Python 3.5|Python 3.6|Runs*  |Works**|
  |-----------------|----------|----------|----------|-------|-------|
  |PyQt4            |Yes       |Yes       |Yes       |?      |?      |
  |PyQt5 (5.8.2)    |No        |Yes       |Yes       |Yes    |Yes    |
  |cx-Freeze (5.0.1)|Yes       |Yes       |Yes       |Yes    |Yes    |
  |py2exe (0.9.2.2) |Yes       |No        |No        |Yes    |No     |
  |pyinstaller***   |Yes       |Yes***    |No        |Yes    |No     |
  </code></pre>
  
  <p><sub>*Command executes or package imports without errors</sub></p>
  
  <p><sub>**Result of command is valid (i.e. produces working freeze)</sub></p>
  
  <p><sub>***Supported in dev branch</sub></p>
  
  <p>I have tried using the latest versions of py2exe and pyinstaller with Python 3.4/3.5/3.6 separately with no success. The errors I receive are different and complicated each time, and my debugging and research into it was unsuccessful for each pairing of Python version and either freezer package. I won't have enough time to delve into that anytime soon.</p>
  
  <p>PyQt4 is not a practical option because it lacks some very important features like HiDPI support and it uses deprecated QtWebKit.</p>
  
  <p>PyQt5 is only compatible with Python 3.5 and up because its <code>sip</code> package requires it.</p>
  
  <p>py2exe supports UPX and single file (.exe) output but doesn't go past Python 3.4.</p>
  
  <p>pyinstaller dev branch runs in 3.5, but I could not get it to copy binaries to the output directory properly. Every time I run it I get a error messages about not being able to find Qt5 libs. It's different ones each time I run it.</p>
  
  <p>cx-Freeze, on the other hand, is working with some <a href="https://stackoverflow.com/questions/41669260/">guidance</a> in <code>setup.py</code>:</p>
  
  <pre><code>build_options = dict(
      packages = ['encodings', 'asyncio', 'jinja2'],
      ...
  )
  </code></pre>
  
  <p>Now this is great. It produces a working freeze but my only remaining concern is how should I turn this 300MB folder of frozen <em>stuff</em> (70 files/folders!) into something a little more manageable (ideally under 30MB)? For example, all of the (pre-compiled) Qt5 libraries are copied into the destination twice, in two different paths: <code>build\exe.win-amd64-3.6</code> and <code>build\exe.win-amd64-3.6\PyQt5\Qt\bin</code>. I can delete the DLLs in <code>build\exe.win-amd64-3.6</code> and the program still runs fine. And the dependency <code>QtWebEngineCore.dll</code> weighs in at 65MB (uncompressed) and about 26MB after running it through UPX on <code>-9</code> maximum compression (that's a good start).</p>
  
  <p>My goal is to minimize the footprint of my application, and currently, my flask-python program is a memory hog:</p>
  
  <p>My flask-desktop program hogging a lotta memory</p>
  
  <p><img src="https://i.stack.imgur.com/uc0xX.png" alt=""></p>
  
  <p>What suggestions do you have for having (Py)Qt5-based application using QtWebEngine use less memory? Also, I'm not familiar with cx-Freeze, so I would love to know if anyone could suggest how I can reduce the build output size with it or how I might get another package freezer to work with Python 3.5/3.6 and PyQt5.</p>
  
  <p>I feel like I have explored a lot of options here but I am still running into difficult limitations because of Python/package version incompatibilities. Any help is greatly appreciated.</p>