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. 🐍