Background

Sometimes we have different python versions required for various projects, and pyenv is a beautiful tool to make it happen. Unfortunately, the Mac M1 chip is relatively new to the x86 design, so there're sometimes a few strange problems when we try to install python via pyenv, and this blog will share how I install it.

Installation

If everything goes well, it should be straightforward to install python through the pyenv.

  1. Install pyenv first.
brew install pyenv
  1. Initialize pyenv: To make sure pyenv is properly set up, run the following commands in your terminal:
echo -e 'if command -v pyenv 1>/dev/null 2>&1; then\n  eval "$(pyenv init -)"\nfi' >> ~/.bash_profile
source ~/.bash_profile

if you are usiong zsh, please replace the /.bash_profile to ~/.zshrc.

  1. Install python 3.10.9
pyenv install 3.10.9
  1. Verify the installation
python --version

you should see there's Python 3.10.9 in your local list. That's it, pretty simple if all works fine, but sometimes there are some surprises.

Errors

Here's an error I faced

dyld[56600]: symbol not found in flat namespace '_libintl_bindtextdomain'
/bin/sh: line 1: 56600 Abort trap: 6           DYLD_LIBRARY_PATH=/var/folders/73/543qbm7n423dx355b3fvwv3c0000gn/T/python-build.20230210180100.46439/Python-3.10.9 ./python.exe -E -S -m sysconfig --generate-posix-vars
generate-posix-vars failed
make: *** [pybuilddir.txt] Error 1

This error message suggests that there is an issue with the localization libraries (libintl) required by Python. It seems that these libraries are not found in the flat namespace and are causing the build to fail.

we try reinstalling the missing libraries

brew reinstall gettext

next, specify the include and library directories when building Python

CFLAGS="-I$(brew --prefix gettext)/include" LDFLAGS="-L$(brew --prefix gettext)/lib" pyenv install 3.10.9

and I need to share my existed CFLAGS & LDFLAGS settings in the .zshrc, if you need to, you should combine both.

export LDFLAGS="-L$(brew --prefix openssl)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix zlib)/lib -L$(brew --prefix bzip2)/lib -L$(brew --prefix gettext)/lib -L$(brew --prefix libffi)/lib"
export CPPFLAGS="-I$(brew --prefix libffi)/include -I$(brew --prefix openssl)/include -I$(brew --prefix readline)/lib"
export CFLAGS="-I$(brew --prefix openssl)/include -I$(brew --prefix bzip2)/include -I$(brew --prefix readline)/include -I$(xcrun --show-sdk-path)/usr/include"

Finally, verify the installation agian, and it works

python --version

Conclusion

This blog shows how to successfully install a new python version through pyenv in the Mac M1; happy enjoy it; if there's any mistake, please leave a comment to let me know thanks,