uwsgi fails under pyenv/2.7.11 with _io.so: undefi

2019-08-07 23:25发布

问题:

when i start uwsgi 2.0.11.2 under pyenv 2.7.11 i get:

ImportError: /home/user/.pyenv/versions/2.7.11/envs/master2/lib/python2.7/lib-dynload/_io.so: undefined symbol: _PyCodecInfo_GetIncrementalEncoder

also uwsgi prints Python version: 2.7.10 (default, May 30 2015, 13:57:08) [GCC 4.8.2]

not sure how to fix it

回答1:

I had the same (or better: a similar) problem with uwsgi when upgrading Python from 2.7.3 to 2.7.10:

  • The module that I tried to import was socket (socket.py)
    • Which in turn tried to import _socket (_socket.so) - and the unresolved symbol was _PyInt_AsInt

The problem is a mismatch between some functions between Python minor minor releases (which doesn't break any backward compatibility, BTW). Let me detail:

  • Build time: when your uwsgi was built, the build was against Python 2.7.10 (as you specified). Python could have been compiled/built:

    • statically - most likely, the PYTHON LIBRARY (from now on, I am going to refer to it as PYTHONCORE as it's named by its creators) in this case: (libpython2.7.a) is in a static lib which is included in the python executable resulting a huge ~6MB executable
    • dynamically - PYTHONCORE (libpython2.7.so) is a dynamic library which python executable (~10KB of bytes large, this time) uses at runtime
  • Run time: the above uwsgi must run in an Python 2.7.11 environment

Regardless of how Python is compiled, the following thing happened: between 2.7.10 and 2.7.11 some internal functions were added/removed (in our case added) from both:

  • PYTHONCORE
  • Dynamic (or extension) modules (written in C) - .so files located in ${PYTHON_LIB_DIR}/lib-dynload (e.g. /home/user/.pyenv/versions/2.7.11/envs/master2/lib/python2.7/lib-dynload); any dynamic module (.so) is a client for PYTHONCORE

So, basically it's a version mismatch (encountered at runtime):

  • 2.7.10 (which uwsgi was compiled against):

    • PYTHONCORE - doesn't export PyCodecInfo_GetIncrementalEncoder
    • _io.so (obviously) doesn't use the exported func (so, no complains at import time)
  • 2.7.11 (which uwsgi is run against):

    • PYTHONCORE - still (as it was "embedded" in uwsgi at compile (build) time, so it's still 2.7.10) doesn't export PyCodecInfo_GetIncrementalEncoder
    • _io.so - uses/needs it

resulting a situation where a Python 2.7.11 dynamic module was used against Python 2.7.10 runtime, which is unsupported.

As a conclusion make sure that your uwsgi buildmachine is in sync (from Python PoV) with the runmachine, or - in other words - build uwsgi with the same Python version you intend to run it with!



回答2:

CristiFati covered the why part. The exact how to for me was:

cd my_pyenv_virtualenv
wget http://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar xf uwsgi-latest.tar.gz
cd uwsgi-2.0.11.2
python uwsgiconfig.py --build
mv uwsgi /home/user/.pyenv/versions/2.7.11/envs/master2/bin/uwsgi


回答3:

I had the same error on RHEL, and eventually discovered it was due to the tsch shell I was using. I solved the problem by switching to the bash shell:

bash

which allowed my script to run fine.