How to set the default encoding in a buildout script, or during virtualenv creation?
Question: I have a Plone project which is created by a `buildout` script and needs a
default encoding of `utf-8`. This is usually done in the `sitecustomize.py`
file of the Python installation. Since there is a `virtualenv`, I'd like to
generate this file automatically, to contain something like:

    
    
    import sys
    sys.setdefaultencoding('utf-8')
    

After generation I have two empty `sitecustomize.py` files - one in
`parts/instance/`, and one in `parts/buildout`; but none of these seems to be
used (I couldn't find them in `sys.path`).

I tried `zopepy`:

    
    
    >>> from os.path import join, isfile
    >>> from pprint import pprint
    >>> import sys
    >>> pprint([p for p in sys.path
    ...         if isfile(join(p, 'sitecustomize.py'))
    ...         ])
    

and found another one in my local `lib/python2.7/site-packages/` directory
which looks good; but it doesn't work:

    
    
    >>> import sys
    >>> sys.getdefaultencoding()
    'ascii'
    

This directory sits near the end of the `sys.path`, because I needed to add it
by an `extra-paths` entry (to get another historical package).

Any pointers? Thank you!

**System information** : CentOS 7, Python 2.7.5

**Edit** : I deleted them two empty `sitecustomize.py` files; now I have a
default encoding of `utf-8` in the `zopepy` session but still `ascii` in
Plone; this surprises me, because I have in my buildout script:

    
    
    [zopepy]
    recipe=zc.recipe.egg
    eggs = ${instance:eggs}
    extra-paths = ${instance:extra-paths}
    interpreter = zopepy
    scripts = zopepy
    

To debug this, I created a little function which I added to my code, and which
displays a little information about relevant modules in the `sys.path`:

    
    
    import sys
    from os.path import join, isdir, isfile
    
    def sitecustomize_info():
        plen = len(sys.path)
        print '-' * 79
        print 'sys.path has %(plen)d entries' % locals()
        for tup in zip(range(1, plen+1), sys.path):
            nr, dname = tup
            if isdir(dname):
                for fname in ('site.py', 'sitecustomize.py'):
                    if isfile(join(dname, fname)):
                        print '%(nr)4d. %(dname)s/%(fname)s' % locals()
                spname = join(dname, 'site-packages', 'sitecustomize.py')
                if isfile(spname):
                    print '%(nr)4d. %(spname)s' % locals()
            else:
                print  '?     %(dname)s is not a directory' % locals()
        print '-' * 79
    

Output:

    
    
    sys.path has 303 entries
       8. /usr/lib64/python2.7/site-packages/sitecustomize.py
     295. /opt/zope/instances/wnzkb/lib/python2.7/site-packages/sitecustomize.py
    ?     /usr/lib64/python27.zip is not a directory
     298. /usr/lib64/python2.7/site.py
    ?     /usr/lib64/python2.7/lib-tk is not a directory
    ?     /usr/lib64/python2.7/lib-old is not a directory
     303. /usr/lib/python2.7/site-packages/sitecustomize.py
    

All `sitecustomize.py` files look the same (switching to `utf-8`), and I
didn't tweak `site.py` (for now; if everything else fails, I might need to.)


Answer: If you **really** want/need to use the `sitecustomize.py` trick, you could
include this part in your buildout:

    
    
    [fixencode]
    recipe = plone.recipe.command
    stop-on-error = yes
    update-command = ${fixencode:command}
    command =
        SITE_PACKAGES=$(${buildout:executable} -c \
          'from distutils.sysconfig import get_python_lib;print(get_python_lib())')
        cat >  $SITE_PACKAGES/../sitecustomize.py << EOF
        #!${buildout:executable} -S
        import sys
        sys.setdefaultencoding('utf-8')
        EOF
    

It will be added into the site-packages folder from your virtualenv.

