<div dir="ltr">The following relates to Python3.4, PyQt5.4, and OS X 10.10.<br><br>While trying to bundle an app for distribution I found that<br>the behavior of QSettings differs between the app when run by<br>CPython from the command line, and when it runs in a “bundle”<br>as prepared by cx_freeze[1] OR by PyInstaller[2].<br><br>The apps made by either bundling method fail in the<br>identical way. That is why I am bringing this to the PyQt<br>list first. I have reduced it to a bare minimum of code<br>in hopes someone can suggest what to investigate next.<br><br><span style="font-family:monospace,monospace">[14:04:48 scratch] cat writer.py<br>from PyQt5.QtCore import QCoreApplication, QSettings<br>app = QCoreApplication([])<br>app.setOrganizationName("BOGUS_NAME")<br>app.setOrganizationDomain("<a href="http://bogosity.com" target="_blank">bogosity.com</a>")<br>app.setApplicationName("BOGUS_APP")<br>settings = QSettings()<br>settings.clear()<br>settings.setValue('b',b'\xde\xad\xbe\xef')<br><br>[14:04:53 scratch] cat reader.py<br>from PyQt5.QtCore import QCoreApplication, QSettings<br>app = QCoreApplication([])<br>app.setOrganizationName("BOGUS_NAME")<br>app.setOrganizationDomain("<a href="http://bogosity.com" target="_blank">bogosity.com</a>")<br>app.setApplicationName("BOGUS_APP")<br>settings = QSettings() # open settings file<br>assert b'\xde\xad\xbe\xef' == settings.value('b',b'\x00')</span><br><br>All is nominal when run from the command line:<br><br><span style="font-family:monospace,monospace">[14:04:56 scratch] python3 writer.py<br>[14:05:01 scratch] python3 reader.py<br></span><br>The cx_freeze reader fails.<br><br><span style="font-family:monospace,monospace">[14:05:23 scratch] cxwork/dist/reader<br>Traceback (most recent call last):<br>  File "reader.py", line 7, in <module><br>    assert b'\xde\xad\xbe\xef' == settings.value('b',b'\x00')<br>TypeError: unable to convert a QVariant back to a Python object<br></span><br><br>The pyinstaller reader also fails the same way.<br><br><span style="font-family:monospace,monospace">[14:05:41 scratch] piwork/dist/reader/reader<br>Traceback (most recent call last):<br>  File "<string>", line 7, in <module><br>TypeError: unable to convert a QVariant back to a Python object<br></span><br>Remake the Settings file using a bundled writer:<br><br><span style="font-family:monospace,monospace">[14:05:48 scratch] rm ~/Library/Preferences/com.bogosity.BOGUS_APP.plist <br>[14:06:12 scratch] piwork/dist/writer/writer<br></span><br>Now the normal reader fails also.<br><br>[<span style="font-family:monospace,monospace">14:06:23 scratch] python3 reader.py<br>Traceback (most recent call last):<br>  File "reader.py", line 7, in <module><br>    assert b'\xde\xad\xbe\xef' == settings.value('b',b'\x00')<br>TypeError: unable to convert a QVariant back to a Python object</span><br><br>But so do the bundled readers<br><br><span style="font-family:monospace,monospace">[14:06:30 scratch] piwork/dist/reader/reader<br>Traceback (most recent call last):<br>  File "<string>", line 7, in <module><br>TypeError: unable to convert a QVariant back to a Python object</span><br><br>The cxfreeze reader and writer tests are the same, omitted.<br><br>To recap: the Settings plist written by the “normal” writer<br>can be read only by the “normal” reader. The plist written<br>by either bundled writer cannot be read by ANY reader.<br><br>So is there a difference in output of a normal versus a bundled writer?<br><br><br>[<span style="font-family:monospace,monospace">14:07:04 scratch] rm ~/Library/Preferences/com.bogosity.BOGUS_APP.plist <br>[14:07:11 scratch] python3 writer.py<br>[14:07:16 scratch] hexdump -C ~/Library/Preferences/com.bogosity.BOGUS_APP.plist <br>00000000  62 70 6c 69 73 74 30 30  d1 01 02 51 62 6f 10 2f  |bplist00...Qbo./|<br>00000010  00 40 00 56 00 61 00 72  00 69 00 61 00 6e 00 74  |.@.V.a.r.i.a.n.t|<br>00000020  00 28 00 00 00 00 00 00  00 7f 00 00 00 00 00 00  |.(..............|<br>00000030  00 0e 00 50 00 79 00 51  00 74 00 5f 00 50 00 79  |...P.y.Q.t._.P.y|<br>00000040  00 4f 00 62 00 6a 00 65  00 63 00 74 00 00 00 00  |.O.b.j.e.c.t....|<br>00000050  00 00 00 00 00 0b 00 80  00 03 00 43 00 04 00 de  |...........C....|<br>00000060  00 ad 00 be 00 ef 00 71  00 00 00 2e 00 29 08 0b  |.......q.....)..|<br>00000070  0d 00 00 00 00 00 00 01  01 00 00 00 00 00 00 00  |................|<br>00000080  03 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|<br>00000090  6e                                                |n|<br><br></span><br><span style="font-family:monospace,monospace"><br>[14:07:23 scratch] rm ~/Library/Preferences/com.bogosity.BOGUS_APP.plist <br>[14:07:28 scratch] piwork/dist/writer/writer<br>[14:07:37 scratch] hexdump -C ~/Library/Preferences/com.bogosity.BOGUS_APP.plist <br>00000000  62 70 6c 69 73 74 30 30  d1 01 02 51 62 5f 10 24  |bplist00...Qb_.$|<br>00000010  40 56 61 72 69 61 6e 74  28 00 00 00 7f 00 00 00  |@Variant(.......|<br>00000020  0e 50 79 51 74 5f 50 79  4f 62 6a 65 63 74 00 00  |.PyQt_PyObject..|<br>00000030  00 00 00 29 08 0b 0d 00  00 00 00 00 00 01 01 00  |...)............|<br>00000040  00 00 00 00 00 00 03 00  00 00 00 00 00 00 00 00  |................|<br>00000050  00 00 00 00 00 00 34                              |......4|</span><br><br>One immediate difference appears: the strings in the “normal”<br>plist are in UTF-16(?), those in the “bundled” plist are ASCII.<br>Another is that the byte string values "deadbeef" which are visible<br>in the normal plist (offset 05f forward) are not visible in the other.<br><div><div><br>This would explain why the “normal” reader cannot read the<br>“bundled” plist - if it expected 16-bit chars. It might explain why the<br></div><div>"bundled" reader can't read the "normal" plist (if it expects ASCII)<br></div><div>and why it can't read a "bundled" plist (if the item value is munged/omitted).<br></div><br>I need to make a "bundled" app work with QSettings, and<br>would love any suggestions as to what to look at next.<br><br>Thanks for your attention.<br><br>[1] <a href="http://cx-freeze.sourceforge.net/" target="_blank">http://cx-freeze.sourceforge.net/</a><br>[2] <a href="https://github.com/pyinstaller/pyinstaller/wiki" target="_blank">https://github.com/pyinstaller/pyinstaller/wiki</a></div><br><br></div>