All Projects → mrkn → Pycall.rb

mrkn / Pycall.rb

Licence: mit
Calling Python functions from the Ruby language

Programming Languages

python
139335 projects - #7 most used programming language
c
50402 projects - #5 most used programming language
ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to Pycall.rb

Featexp
Feature exploration for supervised learning
Stars: ✭ 688 (-11%)
Mutual labels:  data-science
Industry Machine Learning
A curated list of applied machine learning and data science notebooks and libraries across different industries (by @firmai)
Stars: ✭ 6,077 (+686.16%)
Mutual labels:  data-science
Rows
A common, beautiful interface to tabular data, no matter the format
Stars: ✭ 739 (-4.4%)
Mutual labels:  data-science
Sciblog support
Support content for my blog
Stars: ✭ 694 (-10.22%)
Mutual labels:  data-science
Reflow
A language and runtime for distributed, incremental data processing in the cloud
Stars: ✭ 706 (-8.67%)
Mutual labels:  data-science
Machine learning examples
A collection of machine learning examples and tutorials.
Stars: ✭ 6,466 (+736.48%)
Mutual labels:  data-science
Learn Julia The Hard Way
Learn Julia the hard way!
Stars: ✭ 679 (-12.16%)
Mutual labels:  data-science
Awesome Interpretable Machine Learning
Stars: ✭ 763 (-1.29%)
Mutual labels:  data-science
Statistical Rethinking With Python And Pymc3
Python/PyMC3 port of the examples in " Statistical Rethinking A Bayesian Course with Examples in R and Stan" by Richard McElreath
Stars: ✭ 713 (-7.76%)
Mutual labels:  data-science
Prefect
The easiest way to automate your data
Stars: ✭ 7,956 (+929.24%)
Mutual labels:  data-science
H1st
The AI Application Platform We All Need. Human AND Machine Intelligence. Based on experience building AI solutions at Panasonic: robotics predictive maintenance, cold-chain energy optimization, Gigafactory battery mfg, avionics, automotive cybersecurity, and more.
Stars: ✭ 697 (-9.83%)
Mutual labels:  data-science
Cookbook 2nd
IPython Cookbook, Second Edition, by Cyrille Rossant, Packt Publishing 2018
Stars: ✭ 704 (-8.93%)
Mutual labels:  data-science
Bowtie
Create a dashboard with python!
Stars: ✭ 724 (-6.34%)
Mutual labels:  data-science
Data Science Interview Resources
A repository listing out the potential sources which will help you in preparing for a Data Science/Machine Learning interview. New resources added frequently.
Stars: ✭ 690 (-10.74%)
Mutual labels:  data-science
Mit 15 003 Data Science Tools
Study guides for MIT's 15.003 Data Science Tools
Stars: ✭ 743 (-3.88%)
Mutual labels:  data-science
Querido Diario
📰 Brazilian government gazettes, accessible to everyone.
Stars: ✭ 681 (-11.9%)
Mutual labels:  data-science
Python Small Examples
告别枯燥,致力于打造 Python 实用小例子,更多Python良心教程见 Python中文网 http://www.zglg.work
Stars: ✭ 6,589 (+752.39%)
Mutual labels:  data-science
Awesome Streamlit
The purpose of this project is to share knowledge on how awesome Streamlit is and can be
Stars: ✭ 769 (-0.52%)
Mutual labels:  data-science
Machine learning refined
Notes, examples, and Python demos for the textbook "Machine Learning Refined" (published by Cambridge University Press).
Stars: ✭ 750 (-2.98%)
Mutual labels:  data-science
Hitchhikers Guide
The Hitchhiker's Guide to Data Science for Social Good
Stars: ✭ 732 (-5.3%)
Mutual labels:  data-science
pycall.rb logo

PyCall: Calling Python functions from the Ruby language

Build Status Build status

This library provides the features to directly call and partially interoperate with Python from the Ruby language. You can import arbitrary Python modules into Ruby modules, call Python functions with automatic type conversion from Ruby to Python.

Supported Ruby versions

pycall.rb supports Ruby version 2.3 or higher.

Supported Python versions

pycall.rb supports Python version 2.7 or higher.

Note that in Python 2.7 old-style class, that is defined without a super class, is not fully supported in pycall.rb.

Note for pyenv users

pycall.rb requires Python's shared library (e.g. libpython3.7m.so). pyenv does not build the shared library in default, so you need to specify --enable-shared option at the installation like below:

$ env PYTHON_CONFIGURE_OPTS='--enable-shared' pyenv install 3.7.2

Installation

Add this line to your application's Gemfile:

gem 'pycall'

And then execute:

$ bundle

Or install it yourself as:

$ gem install --pre pycall

Usage

Here is a simple example to call Python's math.sin function and compare it to the Math.sin in Ruby:

require 'pycall/import'
include PyCall::Import
pyimport :math
math.sin(math.pi / 4) - Math.sin(Math::PI / 4)   # => 0.0

Type conversions from Ruby to Python are automatically performed for numeric, boolean, string, arrays, and hashes.

Releasing the RubyVM GVL during Python function calls

You may want to release the RubyVM GVL when you call a Python function that takes very long runtime. PyCall provides PyCall.without_gvl method for such purpose. When PyCall performs python function call, PyCall checks the current context, and then it releases the RubyVM GVL when the current context is in a PyCall.without_gvl's block.

PyCall.without_gvl do
  # In this block, all Python function calls are performed without
  # the GVL acquisition.
  pyobj.long_running_function()
end

# Outside of PyCall.without_gvl block,
# all Python function calls are performed with the GVL acquisition.
pyobj.long_running_function()

Debugging python finder

When you encounter PyCall::PythonNotFound error, you can investigate PyCall's python finder by setting PYCALL_DEBUG_FIND_LIBPYTHON environment variable to 1. You can see the log like below:

$ PYCALL_DEBUG_FIND_LIBPYTHON=1 ruby -rpycall -ePyCall.builtins
DEBUG(find_libpython) find_libpython(nil)
DEBUG(find_libpython) investigate_python_config("python3")
DEBUG(find_libpython) libs: ["Python.framework/Versions/3.7/Python", "Python", "libpython3.7m", "libpython3.7", "libpython"]
DEBUG(find_libpython) libpaths: ["/opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib", "/opt/brew/opt/python/lib", "/opt/brew/opt/python/Frameworks", "/opt/brew/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7", "/opt/brew/Cellar/python/3.7.2_1/Frameworks/Python.framework/Versions/3.7/lib"]
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/Python.framework/Versions/3.7/Python
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/Python.framework/Versions/3.7/Python.dylib
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/darwin/Python.framework/Versions/3.7/Python
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/lib/darwin/Python.framework/Versions/3.7/Python.dylib
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/Python.framework/Versions/3.7/Python
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/Python.framework/Versions/3.7/Python.dylib
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/darwin/Python.framework/Versions/3.7/Python
DEBUG(find_libpython) Unable to find /opt/brew/opt/python/lib/darwin/Python.framework/Versions/3.7/Python.dylib
DEBUG(find_libpython) dlopen("/opt/brew/opt/python/Frameworks/Python.framework/Versions/3.7/Python") = #<Fiddle::Handle:0x00007fc012048650>

PyCall object system

PyCall wraps pointers of Python objects in PyCall::PyPtr objects. PyCall::PyPtr class has two subclasses, PyCall::PyTypePtr and PyCall::PyRubyPtr. PyCall::PyTypePtr is specialized for type (and classobj in 2.7) objects, and PyCall::PyRubyPtr is for the objects that wraps pointers of Ruby objects.

These PyCall::PyPtr objects are used mainly in PyCall infrastructure. Instead, we usually treats the instances of Object, Class, Module, or other classes that are extended by PyCall::PyObjectWrapper module.

PyCall::PyObjectWrapper is a mix-in module for objects that wraps Python objects. A wrapper object should have PyCall::PyPtr object in its instance variable @__pyptr__. PyCall::PyObjectWrapper assumes the existance of @__pyptr__, and provides general translation mechanisms between Ruby object system and Python object system. For example, PyCall::PyObjectWrapper translates Ruby's coerce system into Python's swapped operation protocol.

Specifying the Python version

If you want to use a specific version of Python instead of the default, you can change the Python version by setting the PYTHON environment variable to the path of the python executable.

Deploying on Heroku

Heroku's default version of Python is not compiled with the --enabled-shared option and can't be accessed by PyCall. Alternative buildpacks are available, including these that have been reported to work with PyCall:

https://github.com/richgong/heroku-buildpack-python https://github.com/dsounded/heroku-buildpack-python https://github.com/ReforgeHQ/heroku-buildpack-python

These community-developed buildpacks are not supported by Heroku, so it's worth examining the source to make sure the buildpack you use suits your needs. For instance, 'ReforgeHQ' works well with Python 3.8.1, but has not been configured to work with other versions and may not be as generally useful as the 'dsounded' or 'richgong' buildpacks.

The buildpack will expect to find both a runtime.txt and a requirements.txt file in the root of your project. You will need to add these to specify the version of Python and any packages to be installed via pip, e.g to use version Python 3.8.1 and version 2.5 of the 'networkx' package:

$ echo "python-3.8.1" >> runtime.txt
$ echo "networkx==2.5" >> requirements.txt

Commit these two files into project's repository. You'll use these to manage your Python environment in much the same way you use the Gemfile to manage Ruby.

Heroku normally detects which buildpacks to use, but you will want to override this behavior. It's probably best to clear out existing buildpacks and specify exactly which buildpacks from scratch.

First, take stock of your existing buildpacks:

$ heroku buildpack [-a YOUR_APP_NAME]

For a Ruby/Rails application this will typically report the stock heroku/ruby buildpack, or possibly both heroku/ruby and heroku/nodejs.

Clear the list and progressively add back your buildpacks, starting with the Python community-developed buildpack. For example, if ruby and nodejs buildpacks were previously installed, and chosing the 'ReforgeHQ' buildback, your setup process will be similar to this:

$ heroku buildpacks:clear
$ heroku buildpacks:add https://github.com/ReforgeHQ/heroku-buildpack-python -i 1
$ heroku buildpacks:add heroku/nodejs -i 2
# heroku buildpacks:add heroku/ruby -i 3

If you have multiple applications on Heroku you will need to append each of these with application's identifier (e.g. heroku buildpacks:clear -a YOUR_APP_NAME).

With each buildpack we are registering its index (the -i switch) in order to specify the order Heroku will load runtimes and execute bootstrapping code. It's important for the Python environment to be engaged first, as PyCall will need to be able to find it when Ruby-based processes start.

Once you have set up your buildpacks, and have commited both requirements.txt and runtime.txt files to git, deploy your Heroku application as your normally would. The Python bootstrapping process will appear in the log first, followed by the Ruby and so on. PyCall should now be able to successfully call Python functions from within the Heroku environment.

NB It is also possible to specify buildpacks within Docker images on Heroku. See Heroku's documentation on using Docker Images.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/mrkn/pycall.rb.

Acknowledgement

PyCall.jl is referred too many times to implement this library.

License

The gem is available as open source under the terms of the MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].