Hi all,
I'm helping someone setup a BeagleBone Black with Angstrom Linux based
on OpemEmbedded and we've run into an issue executing virtualenv with
Python 2.7. I've narrowed the problem down to
/usr/lib/python2.7/sitecustomize.py. This script, which is executed
during early Python initialization, imports the readline module and, in
the process, prints some escape characters to stdout. When the output of
a script is piped to another process, those unexpected escape characters
are the first to be read.
As an example, executing
python2 -c 'pass' | python2 -c 'print
repr(__import__("sys").stdin.read())'
prints '\x1b[?1034h' when '' (the empty string) is expected.
For virtualenv, you end up with the following error when it tries to
pipe sys.prefix from one python instance to another:
New python executable in env/bin/python
ERROR: The executable env/bin/python is not functioning
ERROR: It thinks sys.prefix is
u'/home/user/volttron/\x1b[?1034h/home/user/volttron/testenv' (should
be u'/home/user/volttron/testenv')
ERROR: virtualenv is not compatible with this system or executable
I have thought of a few solutions to the issue I wanted to bring to the
developers attention:
1. Move sitecustomize.py to sitesetup.py (or something else) and add
/etc/profile.d/pythonsetup.sh to set the PYTHONSETUP environment
variable to that script.
This, IMHO, is probably the best solution as the PYTHONSETUP script is
only executed in interactive mode. It also makes it trivial users to
disable, by unsetting the environment variable, or override/extend, by
setting the environment variable to their desired script.
2. Provide an environment variable, like DISABLE_SITE_READLINE, to
prevent readline configuration in sitecustomize.py.
This is my least favorite solution because Python remains broken by
default and someone has to know about the environment variable to fix it.
3. Use some magic in the sitecustomize script to make it all work as
expected.
This would be a good compromise as it moves the readline configuration
to the PYTHONSETUP execution phase, while still implementing it in
sitecustomize.py and allowing user PYTHONSETUP scripts. Here is the
suggested sitecustomize.py:
# OpenEmbedded sitecustomize.py (C) 2002-2008 Michael 'Mickey' Lauer
<[email protected]>
# GPLv2 or later
# Version: 20081123
# Features:
# * set proper default encoding
# * enable readline completion in the interactive interpreter
# * load command line history on startup
# * save command line history on exit
'''Use readline to make the interactive interpreter more friendly.
The readline module should only be imported in interactive mode because
it has side-effects which may interfere with the output of scripts. But
because sitecustomize is executed at such an early stage of Python
initialization it cannot determine if Python is executed interactively.
Therefore, this script injects itself as the PYTHONSETUP script where
interactivity can be determined. The PYTHONSETUP environment is first
saved in the environment so it can later be restored. Then, PYTHONSETUP
is set to this script. After executing this script as the PYTHONSETUP
script, the original PYTHONSETUP, script is restored and, if set, is
exectuted.
'''
def main():
'''This function wraps up the script to keep the environment clean.'''
import os
def __exithandler():
try:
readline.write_history_file( "%s/.python-history" %
os.getenv( "HOME", "/tmp" ) )
except IOError:
pass
def __registerExitHandler():
import atexit
atexit.register( __exithandler )
def __enableReadlineSupport():
readline.set_history_length( 1000 )
readline.parse_and_bind( "tab: complete" )
try:
readline.read_history_file( "%s/.python-history" %
os.getenv( "HOME", "/tmp" ) )
except IOError:
pass
def __enableDefaultEncoding():
import sys
try:
sys.setdefaultencoding( "utf8" )
except LookupError:
pass
def __execPythonStartup():
try:
filename = os.environ.pop('__PYTHONSTARTUP__')
except KeyError:
os.environ.pop('PYTHONSTARTUP', None)
else:
os.environ['PYTHONSTARTUP'] = filename
if filename:
execfile(filename)
def __savePythonStartup():
try:
os.environ['__PYTHONSTARTUP__'] = os.environ['PYTHONSTARTUP']
except KeyError:
pass
os.environ['PYTHONSTARTUP'] = __file__
if __name__ == '__main__':
# Executing as PYTHONSETUP script
try:
import rlcompleter, readline
except ImportError:
pass
else:
__registerExitHandler()
__enableReadlineSupport()
__execPythonStartup()
else:
# Executing as sitecustomize
__enableDefaultEncoding()
__savePythonStartup()
main()
del main
I can post the above script as a patch, if desired.
Are there other suggestions/solutions?
Thank you,
Brandon
--
_______________________________________________
Openembedded-devel mailing list
[email protected]
http://lists.openembedded.org/mailman/listinfo/openembedded-devel