= rubypython
== Description
RubyPython is a bridge between the Ruby and Python interpreters. It embeds a running Python interpreter in the Ruby application's process using FFI and provides a means for wrapping, converting, and calling Python objects and methods.
RubyPython uses FFI to marshal the data between the Ruby and Python VMs and make Python calls. You can:
== Where
The RubyPython homepage, project description, and main downloads can be found on {RubyForge}[http://rubypython.rubyforge.org/].
Source is kept in sync between {Bitbucket}[http://raineszm.bitbucket.org/rubypython/] and {GitHub}[https://github.com/halostatue/rubypython], but the Bitbucket repository is the canonical repository and where the {issue tracker}[https://bitbucket.org/raineszm/rubypython/issues?status=new&status=open] resides. We use {Hg-Git}[http://hg-git.github.com/] to keep the two repositories in sync.
== Synopsis
RubyPython is fairly easy to start using; there are three phases to its use:
There are also two methods, +RubyPython.session+ and +RubyPython.run+ that will start before running the code provided in the block and stop it afterwards.
=== Basic Usage
require "rubypython"
RubyPython.start # start the Python interpreter
cPickle = RubyPython.import("cPickle") p cPickle.dumps("Testing RubyPython.").rubify
RubyPython.stop # stop the Python interpreter
=== Specific Python Version
require "rubypython"
RubyPython.start(:python_exe => "python2.7") # Can also be a full path
cPickle = RubyPython.import("cPickle") p cPickle.dumps("Testing RubyPython.").rubify
RubyPython.stop # stop the Python interpreter
=== VirtualEnv
RubyPython.start_from_virtualenv("/path/to/virtualenv")
RubyPython.start(:python_exe => "/path/to/virtualenv/bin/python") RubyPython.activate
=== Iterator support
def readfile(): for line in open("/some/file"): yield line
readfile.to_enum.each do |line| puts line end
def iterate_list(): for item in [ 1, 2, 3 ]: yield item
items = [] iterate_list.to_enum.each { |item| items << item } puts items == [ 1, 2, 3 ] # => true
=== Python to Ruby callbacks
def simple_callback(callback, value): return callback(value)
simple_callback(lambda { |v| v * v }, 4) # => 16
def triple(v) v * 3 end
simple_callback(method(:triple), 4) # => 12
=== Python-style Generators
def test_generator(callback): for i in callback(): print "Got %d" % i
test_generator(RubyPython.generator do (0..10).each { |i| RubyPython.yield i } end)
=== Python named arguments (Experimental)
This format is experimental and may be changed.
def foo(arg1, arg2): pass
foo!(:arg2 => "bar2", :arg1 => "bar1")
foo!(arg2: "bar2", arg1: "bar1")
== Features / Problems
=== Features
==== Experimental Features
Calling Python methods or functions that expect keyword arguments, or call any Python method or function with named parameters.
def func(a, b, c): pass
func!(:b => 2, :c => 3, :a => 1) # => [ 1, 2, 3 ]
While we are committed to keeping this feature in place, we have not yet determined that the form (+method!+) is the best way to achieve this functionality.
This mechanism is experimental because the use of the bang at the end of the method to indicate the use of keyword arguments may not be the best use of that feature of Ruby naming.
Changing Python interpreters in a single Ruby program. Under some circumstances, this will partially work. If a native Python extension has been imported (such as +cPickle+), there is a very high likelihood that there will be a segmentation fault because the newly loaded DLL will still refer to the other version's loaded extension. This is not a recommended workflow.
=== Known Problems
== What's planned There are features that are not currently supported in RubyPython that may be considered for future releases, dependent on need, interest, and solutions.
=== Python 3 We do plan on working this, but as none of the projects any of us are working on require Python 3 as of yet, this is not yet started.
=== Simpler Imports It might be nice to have some nice import helpers provided by RubyPython to make the interface more seamless and provide advanced import features:
==== Import Aliasing
from mod2.mod1 import sym as mysym
py :from => "mod2.mod1", :import => "sym", :as => "mysym" py :from => "mod2.mod1", :import => :sym, :as => :mysym py :from => [ :mod2, :mod1 ], :import => :sym, :as => :mysym
import mod1 as mymod
py :import => "mod1", :as => "mymod" py :import => :mod1, :as => :mymod
from mod2.mod1 import *
py :from => "mod2.mod1", :import => :* pyrequire "mod2/mod1" # ruby style imports
=== Catch Exceptions from Ruby
class MyFirstException(Exception): pass
class MySecondException(MyFirstException): pass
def test(): raise MySecondException
begin test rescue MyFirstException => e
puts e.message
end
== Requirements
=== Python Support RubyPython has been tested with the C-based Python interpreter (cpython), versions 2.4 through 2.7. Work is planned to enable Python 3 support, but has not yet been started. If you're interested in helping us enable Python 3 support, please let us know.
=== Ruby Support
It should work with other implementations that support the Ruby FFI gem with no modification.
=== OS Support RubyPython has been extensively tested on Mac OS 10.5 and 10.6, and Ubuntu 10.10 (64-bit Intel). If your platform has a DLL or shared object version of Python and supports the FFI gem, it should work. Feedback on other platforms is always welcome.
== Install gem install rubypython
:include: Contributors.rdoc
:include: License.rdoc