Python vs Ruby, slightly more in-depth

July 13, 2009 § 54 Comments

Disclaimers

Edit (2009/08/04): It is not obvious for many readers that this blog and its articles are meant as opinion piece. It is also not obvious that I like both languages. Just to be clear, I do like both languages.

Introduction

Not too long ago on Reddit, someone posted Python vs Ruby. This kind of comparisons would be more interesting if the author take some time to actually highlights the merit of both languages.

So, let me take a stab at it.

Python has map, reduce, lambda, and list comprehension. Ruby has select, collect, reject, inject, and block, (and lambda).

Edit (2009/08/04): Thanks to everyone who reminded me that Ruby has lambda too.

These techniques allow programmers to perform operations on lists (or dict/hash) effectively. Some of these are not optimized for speed, so do not expect much on speed gain.

Both have set type, collection of distinct values. Set and List/Array are cast able bi-directionally.

Edit (2009/08/08): I forgot about Generator Expression in Python. It looks more or less like list comprehension, but it works using iterator as opposed to containing all values inside in-memory list.

Edit (2009/08/04): I mention lambda as one of the tools that help me manipulating list, not to point out that Python is cool for having lambda (Ruby is cool for having lambda too).

Python does not have anonymous function, but anonymous function maybe out of scope in this section. Because I can simply use lambda.

See:

Reflection and Meta Programming and Monkey Patching

Edit (2009/08/04): Thanks to readers for pointing it out that these are not the same thing. Although they do serve the same purpose for my use cases.

Both languages supports reflection (and meta-programming and monkey patching). That means you have access to the inner working of an object. Python gives you a lot of access via __these_kind_of_methods__ (I never knew what these are called), while Ruby gives you access to everything inside object.

Example of Python monkey patching: You can swapped out object.__class__ with a completely different class. You can also added extra methods to object.__dict__

You can manipulate Python classes on run-time, but not basic classes such as int or basestring. While in Ruby, you can manipulate everything, including replacing/adding methods inside Integer or String. Even though by default attributes are private, Ruby does not try to stop me from accessing them (use send).

As many of you might already know, Rails monkey-patch global object (e.g. object.blank?). I’m glad that Django and Pylons does NOT do that.

eval()/exec() are simply evil (annoys me) in both languages. They make debugging more difficult.

See:

File manipulation

Manipulating files in Python is horrible. The whole os, os.path, shutil, filecmp, tempfile business is convoluted and inconsistent. IMHO, Ruby wins big time.

Documentation

It’s not that easy to read Python documentation because it’s written like a narration. Whereas Ruby documentation follows Javadoc (which is my personal favorite) style. Use apidock.com for even better RTFM experience.

Edit (2009/08/04): Yes. That is my personal preference. If that’s not clear.

Testing

Ruby wins a lot of TDD practitioners. There are plethora of Ruby modules created for making testing experience truly wonderful. See: RSpec, Shoulda, Factory Girl, Selenium.

Python mocking libraries are still not trivial to use. Testing is an area where Python can learn from Ruby (Yes, Selenium also supports Python).

Edit (2009/08/04): Thanks for telling me about windmill!

Visitor Pattern

Visitor pattern is a technique of decoupling logic from object. Often times, there are logic which needs to be shared among objects that do not share the same parent. Decorator is Python’s implementation to visitor pattern, while in Ruby, this could be done by including module/mixin.

Edit (2009/08/04): Example on why I think decorator is visitor pattern (See @InputEvaluator below):

class InputEvaluator(object):

  def __init__(self, func):
    self.func = func

  def __call__(self):
    # add functionality before self.func is executed
    self.func()
    # add functionality after self.func is executed
    # While I'm at it, I can manipulate things inside self.func.__class__, or __name__

They are not PHP

Both do not have GOTO and are general purpose language. They have real objects and objects can persist longer than the life cycle of HTTP request.

As general purpose language, both have interactive console (plus debugger). Useful for testing features that I forgot. PHP5 does have CLI, but seriously…

Although, I have to say PHP’s require_once is nice. That’s 1 thing I have to gripe about in Python, circular import.

Circular Import

A lot of pythonistas say that if programmer have circular import, then s/he usually have bad design. That’s likely to be correct. But, on those rare cases where the design is good, circular import becomes a huge pain in the neck. A good example of this would be:

2 SqlAlchemy model classes which have classmethod that calls the other class. Perfectly legitimate use case, but now both of those model classes have to be put under the same file because of circular import (To NOT have to do this,  create a method that calls the other classmethod). I believe this ruins code maintainability.

Edit (2009/08/04): See commentary’s input on how to avoid this situation.

HTTP and other basic networking

Python comes with webbrowser, urllib2, smtp, http, SocketServer, HttpServer, and more, while Ruby only has net/HTTP

With all those tools, building things like web spider is trivial in Python.

Edit (2009/08/04): This section is just about standard library. I don’t have enough material to elaborate on this. Thus, it’s fair to criticize this section.

Threading

Both are terrible in threading. Python has GIL which limits its threading performance, while Ruby’s threading is leaking memory. (I think 1.9 address this issue. Anyone can confirm this?)

Edit (2009/08/04): Yes! yes! yes! for those who said that Jython and JRuby do not have these problems.

Daemonize

Both does not have daemonize as part of standard library, although it’s very easy to roll my own.

Java

Jython and JRuby exists and both are making using Java significantly more productive.

  • JRuby is actually really nice and have “real” threading implementation.
  • Using Jython for manipulating Swing objects is surprisingly a happy experience.

Modules (for Web Apps)

Both have so many useful modules for building web applications.

Python have: Django, Pylons, web.py, Beautiful Soup, SqlAlchemy, Paste, Werkzeug, Routes (totally “inspired” by Rails), Shove, Pygments, a dozen or so template languages (my favorite is Mako), 4 different JSON modules (cjson is faster than simple-json when looping through 10,000 times. I don’t actually know if this is the best way to benchmark the two), various performance improvement modules (psyco, pyrex, cython)

Ruby have: Rails, Merb, Sinatra, HPricot, DataMapper, Mongrel, ActiveSupport, Moneta, erb, json, RubyInline

Edit (2009/08/04): If it’s not obvious, I am making direct comparison between Python and Ruby here. Yes, I have used all these modules (except Merb and DataMapper. They look awesome though.)

They are both totally interchangeable for building web applications. Both still needs javascript to make awesome looking web applications.

Edit (2009/08/04): I need to elaborate this point, there are modules in both Python and Ruby which sole purpose is to generate javascript code. For front end web development, I prefer to solve javascript problems in javascript. Go jQuery!

IMHO, outside web app realm, Python is better positioned. See: Pyglet, WxWidget, SciPy, etc.

Getting Paid

Python surprisingly lacks of mature library that handles online payments (Python people are not worried about paying customer?). I would appreciate it if anyone can point me to a good payment API in Python.

Whereas Ruby have Payment and ActiveMerchant

Edit (2009/08/04): See comments below for Python payment module.

Big Companies Backing

I believe Python is winning here. Google, Youtube, Yelp, Nasa, Honeywell, etc. use Python. On the other hand, yellowpages.com, AboutUs, and these guys use Ruby. I heard that Amazon Fresh uses RoR, can anyone confirm?

Edit (2009/08/05): Some have suggested that Apple is leaning towards Ruby camp, especially with MacRuby project (link).

Conclusion

These languages are interchangeable for building web application. Neither are more awesome. They get the job done and they make programmers happy.

Thanks HN visitors for giving thoughtful comments! I’ll try my best to keep up with you guys in updating this article.

[fixing layout]

About these ads

Tagged: ,

§ 54 Responses to Python vs Ruby, slightly more in-depth

  • Nice face value comparison of the languages. Thanks.

  • Yuri says:

    Finally a fair comparison…

  • pauln says:

    I’d add to the Python advantages in web apps:
    * twisted
    * eventlets
    * wsgi
    * spawning

    Concurrent programming in Python rocks – largely thanks to the bright minds at Linden Labs.

  • Joe says:

    “It’s not that easy to read Python documentation because it’s written like a narration. Whereas Ruby documentation follows Javadoc (which is my personal favorite)…”

    Stoped reading here.

    • didip says:

      @Joe:

      Can I ask the reason why? Is it because you don’t like javadoc?

      or is it because i was wrong when mentioning that python documentation is written like a narration?

      • jb says:

        > Can I ask the reason why? Is it because you don’t like javadoc?
        Python already have docstrings and the pydoc command. This is the equivalence of javadoc.

        The goal of docs.python.org is different.

      • Joe Mama says:

        “Stoped reading here.”

        obviously not to consult your spellcheck.

    • Adam Nelson says:

      I agree that Python is lacking in good documentation, but Django has fantastic documentation (which, for a web programmer, is hugely important in the rails/django decision).

      However, when you go to a typical Python doc:

      http://www.python.org/doc/2.6.2/library/urlparse.html

      it’s not clear what other options exist in the world, what is important and what is not important, and the version numbers are all over the place. A wiki format would be better.

  • Hang says:

    Your article is good but I hate x vs. y articles that don’t come to a conclusion: which one is better for what purpose. You might start a flame war but you have to come to a conclusion and wrap up your article. Let’s put it another way, if you had to write an app today, which language would you choose between the two? I love Ruby but I would actually go with Python because I have way more experience with it. Python is used everywhere so I encounter it more and use it more. Python is a bit gross under the surface and you can see where the abstraction fails every now and then. Nonetheless, it’s never hindered me from doing what I want and usually makes things easier.

    The “Getting Paid” part is pretty funny.

    • didip says:

      @Hang:

      There are too many articles already that champion either languages.

      The fact that I gloss over what python has to offer is intentional.

      It will be a biased comparison against Ruby if I started to cover Scipy, Pyglet, etc.

  • Andrew says:

    Ruby also has lambda. Especially in 1.9.
    It is ->

    Archeopteryx uses it extensively. check it out on github.

  • For Ruby “outside web app realm”, don’t forget MacRuby which, while still in development, provides native object-for-object compatibility with Objective-C and the Cocoa GUI frameworks on Mac OS X.

    http://www.macruby.org/

    Unlike PyObjC, Ruby objects can inherit directly from Objective-C objects and add functionality to the built-in classes while running at near-native speed.

    • didip says:

      @Geoffrey:

      Thank you for the update, I am not aware about MacRuby news. I thought it was just prototype.

      • I also think it’s fair to include Apple among the Ruby “big company” supporters. Macruby is an officially sponsored Apple project, and Ruby + Rails come pre-installed on OSX. Python does too, to be fair, but in my opinion I feel like Apple is a bit more in the Ruby camp.

  • Alex Grönholm says:

    Concerning the circular import problem in Python, why not just import the other class within the classmethod, instead of the module level? That will allow you to keep them in separate modules.

  • Artur says:

    Hi.
    My opinions are opposite in some of the points:

    Documentation
    Yes, if you came from Java then Python style of documentation can be shocking. Now I like Python docs very much, because they say more with fewer words. It’s easier to read one sentence “the objects behaves like a list” than to review a bunch of methods. Note also that list of methods doesn’t fully specify what an object is, it’s a phantom :).

    Testing
    I don’t like a style of Ruby testing libraries. I don’t think tests need a framework. Look at Python’s nosetests, in which tests can be simple functions with ‘test’ in name. The library itself is mainly a test runner only.

    Visitor Pattern
    I use mixins in Python and this is a nice solutions in some situations.

    Circular Import
    Workaround: execute import inside a function.

    Getting Paid
    I don’t know the subject very well, but eg. Satchmo has nice payment modules.

    Threading
    Threading is a broken model for parallel computations :).

    So it seems I’m a Python lover :). What is interesting I learned Ruby before the RoR times, when it was an exotic thing from Japan :).

    • didip says:

      About testing:
      In ruby, those testing framework supports easy to use mock objects, which can make test suites run faster. I also like the approach of behavior driven development.

      Thanks for informing me about satchmo, I’ll check it out.

  • Regarding threading, you can circumvent the GIL problem with the multiprocessing module, which is new in Python 2.6

  • akitaonrails says:

    Although Ruby doesn’t come out with more complex network standard libraries, as you considered 3rd party libraries in the other sections I think it is fair to say that Ruby has tons of great libraries to deal with network. I don’t think there is a use case in this regard that can’t be done with Ruby. For instance, on the daemonizing area RobustThread and Daemons come to mind.

    The whole monkey-patching debacle is out of proportion. It’s usually the case that people who are not used to it think it is bad, and people who are used to it think it is good. Of course, overusing anything as powerful as that is always a bad idea.

    The Ruby community came out with Github. It is not necessarily due to Ruby, of course, but I think it is a great achievement nonetheless and clearly accelerated a lot of Ruby development efforts.

    The JRuby effort is a bold one. Those guys were able to give us a top notch, really robust, really stable, really fast implementation that gets surprisingly better with each new release. It’s totally ready for prime time and production usage and I would recommend it any day.

    Don’t also forget the deployment arena, where we have such wonderful tools such as Capistrano, Puppet and Chef.

    I think the Python has an edge on the Desktop and Sysadmin arena though, specially because distros such as RedHat/Fedora/CentOS have tools like Yum and Anaconda. It also feels like (I don’t have much experience in this) that Python has an edge on Graphical Toolkit bindings such as with Gtk. Maybe Ruby is just underused in this area where the tools do exist, but I can’t confirm. Anyone?

    Performance-wise Python2 is ridiculously faster than Ruby 1.8. On the other hand Ruby 1.9 is as fast where Python 3 is slower. Interesting twist. Though I don’t think this category is really relevant for 80% of the use cases.

    Big Companies backing is good to have but not necessarily decisive. We probably don’t have Google, but we do have what 37signals would call the “Fortune 5.000″, the other end of the spectrum comprised of hundreds of startups and high-profile products. You will find the obvious examples such as Twitter, YellowPages, Scribd, Hulu, all 37signals products of course, more here: http://rubyonrails.org/applications. Consulting-wise there are big names such as ThoughtWorks and others like HashRocket, Relevance, Pivotal Labs, etc. There are several great hosting companies as well such as Engine Yard, Joyent, Dreamhost, etc.

    Windows support is a win for Python, that’s a given. Ruby is coming back fast though, thanks to the efforts of Luis Lavena: http://antoniocangiano.com/2009/08/04/a-faster-ruby-on-windows-is-possible/

    Community-wise, Python is larger, but I am biased to say that the Ruby one is more dynamic and pragmatic. It’s great to have Peepcode, RailsEnvy, RubyLearning.org, etc. And conferences-wise I think it is also a given that Ruby/Rails is winning hands down. I know, not a technical reason, but community is very important.

    TDD and BDD are areas where Ruby technologies do excel, not only that but on new paradigms such as DSL, led by the efforts of Martin Fowler himself.

    Apple is investing, MacRuby is about to become one of the most important VMs ever. I can clearly see Apple adopting Ruby for desktop apps in the future. They already support a great Ruby-Cocoa framework which is improving incredibly fast.

    None of these points make Python worse, neither make my point of view true, maybe just biased as it will always happen, because programmers are necessarily biased, no matter what they say. I also program in dozens of languages, but I know I am biased here. Just my 2 cents.

  • For the record, Ruby has a wrapper for WxWidgets (http://wxruby.rubyforge.org) which is itself a C++ library. Ruby 1.9 has “real” threads, but the core (MRI/YARV) implementation still has a GIL. This may not be true for one or more of JRuby, IronRuby and Enterprise Ruby, however.

  • mikeal says:

    Windmill is a Selenium competitor written entirely in Python & JavaScript with test writing support for both.

    Includes Django support and an SoC student is working on improvements to that support and Django Admin unittests using Windmill.

    http://www.getwindmill.com

    Even though I write test tools (full disclosure, i’m windmill committer) I’m not much for TDD. In fact i’m not really in to any methodology driven development. I’ve spent too much time in open source to value anything except writing good code, staying transparent, and shipping. Most methodologies force you to sacrifice at least one of those.

    Watching people use the specification driven development tools for Ruby look like hell, crazy amounts of boilerplate generation that I just can’t handle.

    • didip says:

      Thank you for telling me about Windmill. I will definitely check it out.

      I’ve been struggling for the longest time on how to test views and UI behaviors.

    • didip says:

      Furthermore, I like your sentiment about write good code, stay transparent , and shipping.

      I couldn’t agree more.

  • Tero says:

    Most of the compared features are argued with personal taste. For example:

    “It’s not that easy to read Python documentation because it’s written like a narration. Whereas Ruby documentation follows Javadoc (which is my personal favorite) style. Use apidock.com for even better RTFM experience.”

    Some people likes narration style documentation (included me) and other people likes strict apidocs. It’s personal taste.

  • Thanks for the comparison, many relevant areas are covered.

    Personally, I really love Python’s `import` handling (syntactically, while the internals are a different point for a separate article/rant) over others. Packages and modules are created using the file system (directories, `__init__.py`) and seem to be (visually) treated and integrated as objects, as in `import foo.bar as baz`. OTOH, Ruby, PHP et al. use something like `require ‘foo/bar’` that feels unnecessary string-ish and lets the directory part shine through too much, for my taste. It should look a bit less noisy, like `require foo.bar` is fine, to me.

  • Alex Gaynor says:

    I have the following issues with this post:

    1) “Reflection a.k.a Meta Programming a.k.a Monkey Patching”, these are quite simply not the same, and in some cases even orthogonal.

    2) “Python gives you a lot of access via __builtins__, while Ruby gives you access to everything inside object.” Is a statement that makes very little sense, for one thing everything in __builtins__ is in the global scope in Python, secondly Ruby *does not* give you access to everything inside an object, the default attribute access is private.

    3) “eval()/exec() are simply evil in both languages. They make debugging more difficult.” Is a statement that is just ignorant. eval() and exec() serve a purpose, the Python standard library for example makes use of them.

    4) “Manipulating files in Python is horrible. The whole os, os.path, shutil, filecmp, tempfile business is convoluted and inconsistent. IMHO, Ruby wins big time.” Python has multiple libraries, but you fail to in any way describe how they are inconsistent or convoluted. You don’t even say a word about Ruby’s libraries, other than that they win.

    5) Your statement regarding documentation can be summed up as, “I have a personal preference”.

    6) “Decorator is Python’s implementation to visitor pattern” fundamentally makes no sense.

    7) “Python comes with webbrowser, urllib2, smtp, http, SocketServer, HttpServer, and more, while Ruby only has net/HTTP

    With all those tools, building things like web spider is trivial in Python.” So for file manipulation having a lot of libraries is bad, but for web protocols it’s a good thing. Gotcha.

    8) Ruby (MRI) also has a GIL which you fail to mention.

    9) “Both still needs javascript to make awesome looking web applications.” I have never heard a statement more orthogonal to what the discussion is.

    10) “These languages are interchangeable” is in my view a completely absurd statement. Both languages have entirely different philosophies and to try to interchange them would be folly. This article chooses, however, to ignore many of these point such as: Ruby’s everything is an object model vs. Python’s less strict everything is an object model that allows for functions not on classes (for example), or Ruby’s small talk derived message passing OO vs. Python’s attribute access model (more similar to C++/Java).

    • didip says:

      1) Yes i am aware of that, they serve the same purpose for my use cases though.

      2) I never knew what to call these functions (__call__, __init__, __setattr__). If that’s not __builtins__, then I stand corrected.

      3) Coming from my personal experience, multiple times, a function does not exists in the eyes of text editor because it was defined inside string. But calling it evil is overboard, i supposed.

      4) In Ruby, there’s just 1 class to call for all my file related needs.

      5) Yes, that is correct.

      6) I have revised the article to include example.

      7) That is coming from personal experience and I believe that’s true.

      8) That is correct, that’s why both threading implementation doesn’t satisfy me. For threading needs, I like JRuby / Jython.

      9) I updated the article to give more context.

      10) To build web apps? Yes, they are very interchangeable.

  • Karmen says:

    FWIW, commercial sites using Ruby on Rails: http://rubyonrails.org/applications

  • Joao Pedrosa says:

    Regarding “HTTP and other Internet stuff”, Ruby has:

    http://www.ruby-doc.org/stdlib/

    See specifically:

    * net/ftp
    * net/http
    * net/imap
    * net/pop
    * net/smtp
    * net/telnet

    * open-uri

    * openssl

    * ping

    * resolve

    * soap

    * socket

    * webrick

    Among others.

    Plus, Ruby has hundreds and potentially thousands of Ruby gems or extensions and plugins supported outside of the default shipping packages of Ruby. ;-)

    Python does have some advanced libraries, but the basic stuff is quite present in Ruby as well. There is generally a bias regarding the library quality of Python that says that Python has better libraries and Ruby libraries are largely ignored at the same time.

  • “This kind of comparisons would be more interesting if the author take some time to actually highlights the merit of both languages.”

    Which is exactly what I did.

  • […] Python vs Ruby, slightly more in-depth « Rudimentary Art of Programming & Development Good Python v Ruby post – much fairer than the usual language wars stuff. Both these languages are good, and they are similar, and they do have disadvantages too. […]

  • William McVey says:

    You missed a few fairly important routines in python among the functional programming tools you listed. Among those are filter, the entire itertools package, and generator expressions (similar to list comprehensions but without requirement of holding the list entirely in memory through the evaluation).

  • […] Python vs Ruby, slightly more in-depth Rudimentary Art of Programming & Development (tags: python ruby) TagsCategoriasmiudezas Uncategorized   […]

  • Paul says:

    I can confirm that they use RoR at Amazon Fresh, but not for the consumer site, only for order fulfillment at the warehouse. The consumer site uses Java I believe.

  • WalterCool says:

    Using files with python is not hardly… come on!

    a = open(‘file’, ‘ro’) #or ‘rw’ or whenever…
    a.seek(x) #Point to x line
    a.readline() #Read current line and go to next line.

    Too hard? Easiest than java!

  • […] Python vs Ruby, slightly more in-depth […]

  • roger says:

    Ruby block performance is pretty good as long as you don’t use named blocks.

    no block, no nothing

    >> def go; end
    >> Benchmark.realtime { 1000000.times{ go() } }
    => 0.265625

    with block

    >> def go; yield; end
    >> Benchmark.realtime { 1000000.times{ go {} } }
    => 0.625

    with named block
    >> def go █ yield; end
    >> Benchmark.realtime { 1000000.times{ go {} } }
    => 6.75

    That’s on 1.8 anyway. So Ruby’s anonymous blocks are cheaper than named blocks (NB: named blocks are equal in cost to procs or lambdas).

    For me the big difference is still that python 2.5 is faster than ruby 1.9, not to mention more libraries.

    Back to my ruby programming since it’s addictive :)

    -r

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

What’s this?

You are currently reading Python vs Ruby, slightly more in-depth at RAPD.

meta

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: