Error while packing keyring module with PY2APP on MAC OSX

1k views Asked by At

I am making an app in python which needs to store keys. I used keyring module to store keys. I am using python-2.7 and osx 10.8.5 with keyring 3.2( easy_install keyring). Code is running fine on eclipse, but when I converted code into app using py2app, it shows error of MYAPP Error open console Terminate

import keyring
keyring.set_password("title","section","keys")
res= keyring.get_password("title","section")

I included terminal response scrap when typed "python setup.py py2app" while making dist through py2app

byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/__init__.py to keyring/__init__.pyc
creating /Users/fis/Desktop/build/bdist.macosx-10.8-intel/python2.7-semi_standalone/app/collect/keyring
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/backend.py to keyring/backend.pyc
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/core.py to keyring/core.pyc
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/errors.py to keyring/errors.pyc
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/getpassbackend.py to keyring/getpassbackend.pyc
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/py27compat.py to keyring/py27compat.pyc
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/util/__init__.py to keyring/util/__init__.pyc
creating /Users/fis/Desktop/build/bdist.macosx-10.8-intel/python2.7-semi_standalone/app/collect/keyring/util
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/util/platform_.py to keyring/util/platform_.pyc
byte-compiling /Library/Python/2.7/site-packages/keyring-3.2-py2.7.egg/keyring/util/properties.py to keyring/util/properties.pyc
byte-compiling /Library/Python/2.7/site-packages/pathtools-0.1.2-py2.7.egg/pathtools/__init__.pyc to pathtools/__init__.pyc
creating /Users/fis/Desktop/build/bdist.macosx-10.8-intel/python2.7-semi_standalone/app/collect/pathtools
3

There are 3 answers

1
Turix On

Not sure if you ever solved this, but I had a similar issue on my Mac (with python v2.7.6 and py2app v0.9): the script ran fine from the command line (i.e., python scriptname.py), but when I used py2app to convert it to a .app, it failed.

The Console messages led me to conclude that py2app wasn't smart enough to include the submodules from the keyring.backends module. So I explicitly imported everything there and it finally worked:

import keyring.backends.file
import keyring.backends.Gnome
import keyring.backends.Google
import keyring.backends.kwallet
import keyring.backends.multi
import keyring.backends.OS_X
import keyring.backends.pyfs
import keyring.backends.SecretService
import keyring.backends.Windows
import keyring

I hope this helps you!

0
imp On

Include packages='keyring.backends' in setup.py to include all packages of keyring.

3
Dima Tisnek On

I don't have the possibility to try this out locally, here's my best guess:

Try importing all the bits you'll actually need in the app, including exceptions that don't occur during "normal" execution

import keyring
import keyring.set_password as _unused_1
import keyring.backend
import keyring.backend.PasswordSetError as _unused_2

You may also require some other package at runtime, to check that, do the following:

$ python2.7
Python 2.7.5 (default, Sep  6 2013, 09:55:21) 
[GCC 4.8.1 20130725 (prerelease)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> before = sys.modules.keys()
>>> import keyring
>>> middle = sys.modules.keys()
>>> keyring.set_password("a", "b", "c")
Please set a password for your new keyring
Password: 
Password (again): 
Please input your password for the keyring
Password: 
>>> after = sys.modules.keys()
#
# now the interesting bits
#
>>> set(after).difference(set(middle))
set(['struct', 'crypt', 'base64', 'binascii', 'keyring.crypt', 'encodings.base64', 'encodings.base64_codec', '_struct'])
#
# and this
#
>>> set(middle).difference(set(before))
set(['cStringIO', 'heapq', 'logging.threading', 'sre_compile', '_collections', 'logging.cStringIO', '_sre', 'getpass', 'atexit', 'keyring.backend', 'logging.os', 'operator', 'Crypto.Cipher.AES', 'logging.traceback', 'keyring.os', '_heapq', 'logging.time', 'keyring.ConfigParser', 'logging.weakref', 're', 'keyring.getpass', 'sre_constants', 'imp', 'logging.codecs', 'collections', 'logging.thread', 'keyring.imp', 'keyring.logging', 'keyring.keyring', 'string', 'keyring.util.re', 'time', 'Crypto', 'termios', 'keyring.util.escape', 'logging', 'logging.atexit', 'keyring.util', 'logging.sys', 'keyring.abc', 'Crypto.Cipher', 'ConfigParser', 'keyring.util.string', 'keyring.getpassbackend', 'keyword', 'thread', 'strop', 'traceback', 'keyring', 'weakref', 'threading', 'itertools', 'keyring.Crypto', 'keyring.sys', 'sre_parse', 'logging.warnings', 'keyring.core'])

You see how many modules were brought in as a result of import keyring, but also some more modules got brought in as a result of keyring.set_password(...).

Now, most of this should be automatic with py2app, but some runtime dependencies can be missed.

The reason behind this is that py2app does something tricky when it decides which modules to include. Pretend that keyring.set_password() doesn't actually run at this phase. In fact if it did and set_password must have side effects, would you expect py2app to package a plain or modified module?