Ruby/Python Documentation

Table of Contents


Introduction

What is Ruby/Python?

Ruby/Python is a Ruby extension library to embed Python interpreter in Ruby. With this library, you can use the libraries written for Python in your Ruby scripts.

Ruby/Python is designed to integrate the two languages as transparently as possible. Thus you need neither bothersome coding nor special consideration to use Python library. It is much the same as using library written for Ruby.

Simple Example

First of all, let's look at tiny Ruby scripts to access a FTP server with ftplib. The native versions of ftplib are bundled with both Ruby and Python. Though using ftplib via Ruby/Python has no practical meaning, it is a good example.

First, a script using ftplib written in Ruby for Ruby.

require 'ftplib'

ftp = FTP.open('ftp.netlab.co.jp')
ftp.login
ftp.chdir('pub/lang/ruby')
puts ftp.dir
ftp.quit
Very simple. Second, a script using ftplib written in Python for Python via Ruby/Python.
require 'python'
require 'python/ftplib'

ftp = Py::Ftplib::FTP.new('ftp.netlab.co.jp')
ftp.login
ftp.cwd('pub/lang/ruby')
ftp.dir
ftp.quit

Compare the two scripts. There are not so many differences between them. But the latter script uses a library written for Python!

The big difference is the require expressions at the beginning and the naming of class FTP. And there are a few different method names. If you are an experienced Ruby user, you may roughly understand how to use Ruby/Python. As you see, Ruby/Python is a extension library which enables Ruby users to utilize the librares writen for Python as if they were written for Ruby.


Manipulate Python Objects from Ruby

This section describes how to manipulate Python modules and objects with Ruby/Python.

Load Ruby/Python

require 'python'

To use Ruby/Python, You need to load Ruby/Python library. Ruby/Python library itself is a library named 'python'. When Ruby/Python is loaded, a module named Py is defined (under Object). The functionalities of Ruby/Python is provided as modules, classes and module functions under Py module.

eval and exec

Py.eval(PythonExpression)
Py.exec(PythonStatement)

The most simple way to use Python functionalities is to call module functions eval and exec in Py module. These module functions are equivalent of Python's eval builtin function and exec statement. Py.eval evaluates a Python expression and returns the value of the expression. Py.exec executes Python statements.

Example:

list = Py.eval('[1, 2, 3]')     # returns a Python list object
Py.exec('print "hello world"')  # print "hello world" to stdout

Method Invocation

Simple Invocation

obj.method(...)
obj.method?(...)  # returns true or false

You can invoke methods of Python objects. If the method name is suffixed by '?', the value Python method returned is tested as Boolean value and returns true or false. This notation is needed because there are no simple mapping between Python boolean values and Ruby boolean values. If you expect boolean value, you must append '?'. (Python provides no special objects representing boolean value. In Python None, 0, empty list, etc. represent false, and the other objects represent true. Usually Python API uses 0 to represent false. But 0 is true in Ruby.)

Example:

dict = Py.eval('{"One": 1, "Two": 2}') # Python dictionary (hash) object
dict.keys                              # ["One", "Two"]
dict["Two"]                            # 2
dict.has_key("Three")                  # 0 (true in Ruby)
dict.has_key?("Three")                 # false

Keyword Arguments

obj.method([...,] Py::AS_KEYWORD, key1 => val1, key2 => val2, ...)
obj.method([...,] Py::KW, key1 => val1, key2 => val2, ...)

Python methods can receive keyword arguments. But Ruby currently doesn't support keyword arguments. So Ruby/Python do it in it's own fashion as shown above. A specail constant Py::AS_KEYWORD is introduced. (Py::KW is shorthand.) If Py::AS_KEYWORD is found in the argument list, the remaining part of the arguments is interpreted as a hash including keyword arguments. Each keyword name must be a string or a symbol id.

Example:

ftp = Py::Ftplib::FTP.new
ftp.connect(Py::AS_KEYWORD, 'host' => 'ftp.netlab.co.jp', 'port' => 21) # string keyword
ftp.login(Py::KW, :user => 'anonymous', :passwd => 'mail address')      # id keyword

Method Invocation with Block

obj.method(...) {|arg| ...}
When a block is given to Python method invocation, a Proc object is created and passwd as the last argument. So the above expression is equivalent to the following one:
obj.method(..., Proc.new{|arg| ...})

Modules

Import Python Modules

require 'python/module'

Ruby/Python replaces builtin function require. The new require interprets library names prefixed with 'python/' specially. When Library names prefixed with 'python/' is passed, the specified Python module is imported. This is the same as following Python statement.

import module

Imported Python modules look as if they are Ruby modules defined under Py module. When the name of a Python module begins with lower case letters, the Ruby module is defined with capitalized name. Python modules are also refered by attribute referece to the Py module.

Example: Access to Python sys module.

require 'python'      # Py module is defined
require 'python/sys'  # Py::Sys module is defined
Py::Sys               # Reference by constant.
Py.sys                # Attrubute reference to Py module. Same as Py::Sys

Use Python Modules

Functions and attributes defined in Python modules are provided as modules functions.

Example:

require 'python/math'  # Py::Math is defined
Py::Math.sqrt(2)       # 1.41421
Py::Math.pi            # 3.14159

Classes and Types

Mapping to Ruby Class

Python classes and types are mapped to Ruby classes. These classes are defined as subclasses of Py::Object. Thus all Python objects are instance of Py::Object.

Example:

list = Py.eval('[1, 2, 3]')  # Python list type object
list.type                    # Py::Types::ListType class
list.is_a?(Py::Object)       # true

Creating Class Instances

Invocation of class method new defined in each Ruby class correspond to Python class creates a class instance. The arguments passed to new is used as arguments in Python instance creation.

Example:

require 'python/ftplib'
ftp = Py::Ftplib::FTP.new('ftp.netlab.co.jp')
# Equivalent to follwing Python expression.
# ftplib.FTP('ftp.netlab.co.jp')

Object Conversion

Objects go across the boundary between Ruby and Python when they are passed as argument to method invocation. Such objects are automatically converted to the destination language's objects. And when objects are returned as a result of method invocation, opposite coversion is performed.

Objects Passed by Value

Following objects are converted to the destination language's native objects, that is to say, passed by value.

Ruby objectPython objectNote
nilNone
true1(1)
false0(1)
String instancestring
Integer instance Plain Intger or Long Integer
Float instance Floating Point Number
Note:
(1)
These conversions are only performed from Ruby to Python. When converting from Python to Ruby, 0 and 1 are simply converted to Integer instance.

Python Modules, Classes and Types

Ruby Module or Class is defined for each Python module, class and type. Thus these objects are converted to each other.

Objects Passed by Reference

Objects not mentioned above is passed by reference.

When a Python object is passed by reference to Ruby, the object is converted to an instance of a Py::Object's subclass. This object holds the reference to the Python object, and behaves as a proxy to the Python object. When a message is sent to the proxy object, the message is forwarded to the Python object.

When a Ruby object is passed by reference to Python, the object looks as if it is a extension type object from Python. This object also holds the reference to the Ruby object, and forward messages.


API Reference

Modules Classes
fukusima@goto.info.waseda.ac.jp
Last modified: Sun May 9 23:46:57 JST 1999