Example of Pythran Usage Within a Full Project¶
This notebook covers the creation of a simple, distutils-powered, project that ships a pythran kernel.
But first some cleanup
[1]:
!rm -rf hello setup.py && mkdir hello
Project layout¶
The Pythran file is really dumb. The expected layout is:
setup.py
hello/
+---- __init__.py
+---- hello.py
[2]:
%%file hello/hello.py
#pythran export hello()
def hello():
"""
Wave hello.
"""
print("Hello from Pythran o/")
Writing hello/hello.py
And so is the __init__.py
file.
[3]:
%%file hello/__init__.py
"""
Hello package, featuring a Pythran kernel.
"""
from hello import hello
Writing hello/__init__.py
The setup.py
file conatins the classical metadata, plus a special header. this header basically states if pythran is available, use it, otherwise fallback to the python file.
[4]:
%%file setup.py
from distutils.core import setup
try:
from pythran.dist import PythranExtension, PythranBuildExt
setup_args = {
'cmdclass': {"build_ext": PythranBuildExt},
'ext_modules': [PythranExtension('hello.hello', sources = ['hello/hello.py'])],
}
except ImportError:
print("Not building Pythran extension")
setup_args = {}
setup(name = 'hello',
version = '1.0',
description = 'Yet another demo package',
packages = ['hello'],
**setup_args)
Writing setup.py
Running setup.py
¶
With the described configuration, the normal python setup.py
targets should « just work ».
If pythran is in the path, it is used to generate the alternative c++ extension when building a source release. Note the hello.cpp
!
[5]:
%%sh
rm -rf build dist
python setup.py sdist 2>/dev/null 1>/dev/null
tar tf dist/hello-1.0.tar.gz
hello-1.0/
hello-1.0/hello/
hello-1.0/hello/hello.cpp
hello-1.0/hello/hello.py
hello-1.0/hello/__init__.py
hello-1.0/setup.py
hello-1.0/PKG-INFO
But if pythran is no longer in the PYTHONPATH
, the installation does not fail: the regular Python source can still be used.
[6]:
%%sh
rm -rf build dist
PYTHONPATH= python setup.py sdist 2>/dev/null 1>/dev/null
tar tf dist/hello-1.0.tar.gz
hello-1.0/
hello-1.0/hello/
hello-1.0/hello/hello.py
hello-1.0/hello/__init__.py
hello-1.0/setup.py
hello-1.0/PKG-INFO
In case of binary distribution, the native module is generated alongside the original source.
[7]:
%%sh
rm -rf build dist
python setup.py bdist 2>/dev/null 1>/dev/null
tar tf dist/hello-1.0.linux-x86_64.tar.gz | grep 'hello/.*' -o
hello/
hello/__init__.pyc
hello/hello.pyc
hello/hello.so
hello/hello.py
hello/__init__.py
And if pythran is not in the PYTHONPATH
, this still work \o/
[8]:
%%sh
rm -rf build dist
PYTHONPATH= python setup.py bdist 2>/dev/null 1>/dev/null
tar tf dist/hello-1.0.linux-x86_64.tar.gz | grep 'hello/.*' -o
hello/
hello/__init__.pyc
hello/hello.pyc
hello/hello.py
hello/__init__.py