For several years the Python world has been in a state of transition from version 2.x to 3.x. Much code still exists for Python2 in the form of applications, modules, and packages and will likely be supported for some time to come. Python3 is gaining acceptance, especially with new development and many modules and packages are now available for Python3. The Python developers have taken care to ensure that Python2 and Python3 and their respective modules and packages can be installed concurrently. The steps below take advantage of this feature to install Hamlib.py modules for both Python versions. Complete installation of each Python version including their respective development files are required for successful generation of the bindings by SWIG. At this time the GNU Autotools do not offer a clean method of building SWIG bindings for multiple versions of Python. Some hacks can be found on the Web but until a clean native solution is offered the steps in this document should prove adequate. With the wealth of Python2 programs, modules, and packages still in use, it isn't likely to disappear from distributions anytime soon. Python3 is becoming more popular for new development with a complete standard library and many modules and packages being ported over and available. It's time that we offer a means to generate bindings for either version. This document will provide the steps for doing so. NOTE: Developers and testers building from a Git clone/checkout will need to bootstrap the build system by running the (appropriately named) 'bootstrap' script. Source releases and source daily snapshots already have this step completed. NOTE: The commands assume an out of tree build in a sibling directory to the main source directory. Adjust your paths accordingly. Adjust your --prefix option as needed (installation to the user's home directory is shown to avoid root privileges). Assuming that Python2 is the default installed Python interpreter, build its bindings first: ../hamlib/configure --with-python-binding --prefix=$HOME/local make make install NOTE: Over time Python3 will become the default Python interpreter on most distributions and the extra step will be needed for Python2 as detailed below. At this point the Hamlib binaries, development files, and Python2 bindings will be installed to their customary locations under $HOME/local. Examination of the configure script's output will confirm that Python2 is found and used as this extract shows: checking whether to build python binding and demo... yes checking for python... /usr/bin/python checking for a version of Python >= '2.1.0'... yes checking for the distutils Python package... yes checking for Python include path... -I/usr/include/python2.7 checking for Python library path... -L/usr/lib64 -lpython2.7 checking for Python site-packages path... /usr/lib64/python2.7/site-packages checking python extra libraries... -lpthread -ldl -lutil -lm checking python extra linking flags... -Xlinker -export-dynamic checking consistency of all components of python development environment... yes checking whether /usr/bin/python version is >= 2.1... yes checking for /usr/bin/python version... 2.7 checking for /usr/bin/python platform... linux2 checking for /usr/bin/python script directory... ${prefix}/lib64/python2.7/site-packages checking for /usr/bin/python extension module directory... ${exec_prefix}/lib64/python2.7/site-packages At this point the file pytest.py in the source bindings directory may be run as a test. If an error is given that the Hamlib module cannot be found, see below. The next step is to configure and build for Python3: ../hamlib/configure --with-python-binding PYTHON_VERSION='3.6' --prefix=$HOME/local If that doesn't work try: ../hamlib/configure --with-python-binding PYTHON=$(which python3) --prefix=$HOME/local then do the build: cd bindings make NOTE: By changing the current directory to 'bindings', only the new Python3 module will be compiled, which speeds things up considerably. Here the PYTHON_VERSION environment variable is set to the Major.minor version of Python we wish to build against. The build system should be able to set everything correctly from this environment variable. If not, try the second example line which sets the PYTHON environment variable to the first python3 executable found in the path (python3 may be a symbolic link, which is fine). This may be unwanted behavior if multiple versions of Python are installed so a specific version with the full path may also be provided. Python3 was found as shown in this configure output extract: checking whether to build python binding and demo... yes checking for python3.6... /usr/bin/python3.6 checking for a version of Python >= '2.1.0'... yes checking for the distutils Python package... yes checking for Python include path... -I/usr/include/python3.6m checking for Python library path... -L/usr/lib64 -lpython3.6m checking for Python site-packages path... /usr/lib64/python3.6/site-packages checking python extra libraries... -lpthread -ldl -lutil -lm checking python extra linking flags... -Xlinker -export-dynamic checking consistency of all components of python development environment... yes checking whether /usr/bin/python3.6 version is >= 2.1... yes checking for /usr/bin/python3.6 version... 3.6 checking for /usr/bin/python3.6 platform... linux checking for /usr/bin/python3.6 script directory... ${prefix}/lib64/python3.6/site-packages checking for /usr/bin/python3.6 extension module directory... ${exec_prefix}/lib64/python3.6/site-packages Since all the Makefiles were regenerated by the second run of configure, hamlib will be compiled again. Next install only the Python3 bindings (still in 'bindings' as the current directory): make install In this case, only the generated files in 'bindings' will be installed which will be the new Python3 bindings. Test that the Hamlib Python3 bindings are found by running the bindings/py3test.py script. At this point working bindings are installed and have been tested. Running 'make uninstall' will only remove the version of the bindings that was last configured. To uninstall the other version the respective options will need to be passed to 'configure' and 'make uninstall' run again. What to do if Python complains the module cannot be found. There are various ways that a specific path can be provided to Python. Perhaps the easiest is to provide an environment variable to your script. Since Python will not have $HOME/local/... in its search path, here is an example: $ py3test.py Traceback (most recent call last): File "./py3test.py", line 9, in import Hamlib ModuleNotFoundError: No module named 'Hamlib' This isn't good! Let's set an environment variable for the running script: PYTHONPATH=$HOME/local/lib64/python3.6/site-packages:$PYTHONPATH ./py3test.py Success! Like the standard PATH environment variable PYTHONPATH can contain multiple paths separated by colons. In this case, if PYTHONPATH was already set the new path is prepended to its prior setting. While setting the environment variable is good for a one-off run, a more permanent solution can be achieved by placing a file that ends in .pth in a directory that Python will process when starting. The special place is: ~/.local/lib64/python3.6/site-packages A .pth file must be set for each major.minor version of Python. Here is an example for Python 2.7: $HOME/.local/lib64/python2.7/site-packages/home.pth Its content is simple: /home/username/local/lib64/python2.7/site-packages (These examples are from a Slackware box which installs Python modules into the 'lib64' directory. Other distributions may simply use 'lib' or another name.) To verify the path, start the Python interpreter in interactive mode, import the sys module, and check the value of sys.path. It will show a number of paths in the list including the ones above and the directory the interpreter was started from and various system directories. Far more information than this is available in the relevant Python documentation, but this should get your scripts working. Removing (uninstalling) the bindings can be done from the 'bindings' directory. Just be sure that 'configure' is run with the options for either Python2 or Python3 first so that 'bindings/Makefile' will generated for the version to be removed. As always, feedback is welcome: Hamlib Developers 73, Nate, N0NB