HOWTO execute Python code with Ruby

And now for something completely different—executing Python code, from Ruby. Useful for accessing Python standard libraries, re-using code already written in Python without having to port it to Ruby, calculating the air-speed velocity of an unladen swallow, or just for fun.

Install the pycall gem

Make sure you have the pycall gem installed:

gem install pycall

Alternatively add the gem to your Gemfile and install it via bundler.

Check you have Python installed

Unsurprisingly to execute Python code you’ll also need Python installed! You can check what version of Python you are running with the following command:

python --version

If you don’t have Python installed you can download it from python.org or install it with your system package manager (recommended).

Executing Python functions

To get started in your Ruby script you need to require the pycall gem and include the PyCall::Import module. You can then import a Python module using the pyimport method and call its functions directly from Ruby. For example:

require 'pycall/import'

include PyCall::Import

pyimport :os
p os.uname

pyimport :mimetypes
p mimetypes.guess_type('index.html')

pyimport :math
p math.degrees(math.pi / 2)

Built-in functions are callable on the __builtin__ module, which is exposed in Ruby as PyCall.builtins and doesn’t need to be explicitly imported. For example:

require 'pycall'

p PyCall.builtins.sum([1, 2, 3, 4])

Some Python types like booleans, numerics, and strings are converted back to their equivalent Ruby types. Other types like lists and tuples are returned as wrapper classes, which you might want to explicitly convert back to Ruby types.

Executing Python code

Use the PyCall.exec method to execute Python code, and the PyCall.eval method to evaluate Python expressions. For example:

require 'pycall'

PyCall.exec 'def double(x): return x * 2'

p PyCall.eval('double(123)')

p PyCall.eval('(1, 2, 3)')

p PyCall.eval('[pow(2, x) for x in xrange(10)]')

This might be useful for constructing Python data structures or implementing algorithms that are more easily expressed in Python. Same as with eval in Ruby: watch out for issues with escaping, and don’t eval code you don’t trust.

Using a different Python version

By default pycall will use the default python on your system. You can specify a different version of Python by setting the PYTHON environment variable or calling PyCall.init with the path or basename of the python you want to use. For example:

require 'pycall'

PyCall.init('python3')

p PyCall::PYTHON_VERSION

Python 3 recommended where possible. 🐍