Comparison of ruby and python line by line (3/3)

This post is the last part of this comparison. I am going to demonstrate how to develop XML-RPC server and client in Ruby and Python. As I said earlier, I don’t know much about Ruby. Below ruby codes are based on an article in Linux Journal #144. I just tried to develop similar program in Python. There are 2 parts; server and client. Let me start from the server.

  1. Specify executable
    Ruby
    #!/usr/bin/ruby
    Python
    #!/usr/bin/python
  2. Import modules
    Ruby
    require ’net/http’
    require ’rexml/document’
    require ’xmlrpc/server’
    Python
    import sys
    import re
    import urllib
    from xml.dom.ext.reader import Sax2
    from xml.dom.ext import Print
    from xml import xpath
    from SimpleXMLRPCServer import SimpleXMLRPCServer
  3. Initialize regular expressions
    Ruby
    not_in_collection_re = /class="yourEntryWouldBeHereData"/ix
    on_shelf_re = /CHECK SHELF/ix
    checked_out_re = /DUE /ix
    Python
    not_in_collection_re = re.compile(r’class="yourEntryWouldBeHereData"’,re.I)
    on_shelf_re = re.compile(r’CHECK SHELF’,re.I)
    checked_out_re = re.compile(r’DUE ’,re.I)
  4. Declare XML-RPC server
    Ruby
    server = XMLRPC::Server.new(8080)
    Python
    server = SimpleXMLRPCServer((’’,8080))
  5. Add an handler
    Ruby
    server.add_handler(name="atf.books",
                       signature=[’array’,’array’]) do |isbns|
     
      output = []
     
      isbns.each do |isbn|
     
        isbn_output = {’ISBN’ => isbn}
     
        if not isbn.match(/[0-9xX]{10}/)
          isbn_output[’message’] = "ISBN #{isbn} is invalid."
          output << isbn_output
          next
        end
     
        amazon_params = {’Service’ => ’AWSECommerceService’,
                         ’Operation’ => ’ItemLookup’,
                         ’AWSAccessKeyId’ => ’XXXXXXXXXXXXXXXXXXXXXXX’,
                         ’ItemId’ => isbn,
                         ’ResponseGroup’ => ’Medium,OfferFull’,
                         ’MerchantId’ => ’All’}.map{|key,value|"#{key}=#{value}"}.join("&")
     
        amazon_response = Net::HTTP.get_response(’webservices.amazon.com’,
                                                 ’/onca/xml?’ << amazon_params)
     
        xml = REXML::Document.new(amazon_response.body)
     
        new_price = xml.root.elements["Items/Item/OfferSummary/LowestNewPrice/FormattedPrice"]
        if new_price.nil?
          isbn_output[’New’] = "None available"
        else
          isbn_output[’New’] = "#{new_price.text}"
        end
     
        used_price = xml.root.elements["Items/Item/OfferSummary/LowestUsedPrice/FormattedPrice"]
        if used_price.nil?
          isbn_output[’Used’] = "None available"
        else
          isbn_output[’Used’] = "#{used_price.text}"
        end
     
        collectible_price = xml.root.elements["Items/Item/OfferSummary/LowestCollectiblePrice/FormattedPrice"]                   
        if collectible_price.nil?
          isbn_output[’Collectible’] = "None available"
        else
          isbn_output[’Collectible’] = "#{collectible_price.text}"    end
     
        response = Net::HTTP.get_response(’catalog.skokielibrary.info’,
                                        "/search~S4/i?SEARCH=#{isbn}")
          
        if not_in_collection_re.match(response.body)
          isbn_output[’Library’] = "Library: Not in the Skokie collection."
        elsif checked_out_re.match(response.body)
          isbn_output[’Library’] = "Checked out."
        elsif on_shelf_re.match(response.body)
          isbn_output[’Library’] = "On the shelf."
        else
          isbn_output[’Library’] = "Unparseable response."
        end
     
        output << isbn_output
      end
     
      output
    end
    Python
    def atf_books(isbns):
        output = []
     
        for isbn in isbns:
            isbn_output = {’ISBN’: isbn} 
            if not re.match(r’[0-9xX]{10}’,isbn):
                isbn_output[’message’] = ’ISBN %s is invalid.’ % isbn
                output.append(isbn_output)
                continue
     
            amazon_params = {
                ’Service’: ’AWSECommerceService’,
                ’Operation’: ’ItemLookup’,
                ’AWSAccessKeyId’: ’XXXXXXXXXXXXXXXXXXXXXXX’,
                ’ItemId’: isbn,
                ’ResponseGroup’: ’Medium,OfferFull’,
                ’MerchantId’: ’All’,
            }
     
            amazon_response = urllib.urlopen(’http://webservices.amazon.com/onca/xml’,urllib.urlencode(amazon_params))
            xml = Sax2.FromXmlStream(amazon_response).documentElement
     
            try:
                new_price = xpath.Evaluate(’Items/Item/OfferSummary/LowestNewPrice/FormattedPrice’,xml)[0]
                isbn_output[’New’] = new_price.childNodes[0].nodeValue
            except:
                isbn_output[’New’] = ’None available’
     
            try:
                used_price = xpath.Evaluate(’Items/Item/OfferSummary/LowestUsedPrice/FormattedPrice’,xml)[0]
                isbn_output[’Used’] = used_price.childNodes[0].nodeValue
            except:
                isbn_output[’Used’] = ’None available’
     
            try:
                collectible_price = xpath.Evaluate(’Items/Item/OfferSummary/LowestCollectiblePrice/FormattedPrice’,xml)[0]
                isbn_output[’Collectible’] = collectible_price.childNodes[0].nodeValue
            except:
                isbn_output[’Collectible’] = ’None available’ 
    
            response = urllib.urlopen(’http://catalog.skokielibrary.info/search~S4/i’,’SEARCH=%s’ % isbn)
            body = response.read() 
            if not_in_collection_re.search(body):
                isbn_output[’Library’] = ’Library: Not in the Skokie collection.’
            elif checked_out_re.search(body):
                isbn_output[’Library’] = ’Checked out.’
            elif on_shelf_re.search(body):
                isbn_output[’Library’] = ’On the shelf.’
            else:
                isbn_output[’Library’] = ’Unparseable response’
            
            output.append(isbn_output) 
        return output
    
    server.register_function(atf_books,’atf.books’)
  6. Serve clients
    Ruby
    server.serve
    Python
    server.serve_forever()

You might notice a big difference in the 5th step. Ruby allows to write in-line function very easy. To do the same in Python, the procedure must be written in lambda form. I don’t want to use lambda to implement very long code like thist. Instead, I decided to wrap the routine in a function. And again in 6th step, you might find that a method was called without (). I think this is very confusing feature. How can I know the statement is just to refer to the method or to call the method. Then below is the client.

  1. Specify executable
    Ruby
    #!/usr/bin/ruby
    Python
    #!/usr/bin/python
  2. Import modules
    Ruby
    require ’xmlrpc/client’
    Python
    import sys
    from xmlrpclib import ServerProxy
  3. Initialize arguments
    Ruby
    isbns = ARGV
    Python
    isbns = sys.argv[1:]
  4. Declare XML-RPC client
    Ruby
    server = XMLRPC::Client.new2("http://127.0.0.1:8080/",nil,120)
    Python
    server = ServerProxy(’http://127.0.0.1:8080’)
  5. Call a method
    Ruby
    begin
      results = server.call("atf.books",isbns)
    rescue XMLRPC::FaultException => e
      puts "Error:"
      puts e.faultCode
      puts e.faultString
    end
    Python
    try:
        results = server.atf.books(isbns)
    except Exception,why:
        print why
        sys.exit()
  6. Loop through the results
    Ruby
    results.each do |result|
      result.each do |key,value|
        if key == ’ISBN’:
          puts "ISBN: #{value}\n"
        else
          puts "\t#{key}: #{value}\n"
        end
      end
    end
    Python
    for result in results:
        print ’ISBN: %s’ % result[’ISBN’]
        for key,value in result.items():
            if key != ’ISBN’:
                print ’\t%s: %s’ % (key,value)

Can you notice significant difference between Ruby and Python? Ruby’s hash does preserve order but Python doesn’t. So I have to change some logic in the 6th step to show reasonable output.

Don’t forget to read part 1, 2, 3.

Technorati Tags: , , , , , , ,

Video Converter for Mac is

Video Converter for Mac is the most powerful Video Converter for Mac OS software which allows you to convert videos between popular video formats and audio formats. The easy-to-use Video Converter for Mac lets you to enjoy your videos on iPod, PSP, Mobile Phone, Zune, iPhone, Apple TV and MP4/MP3 player. This Video Converter for Mac allows you to set the destination, the name of output files.iPod Converter for Mac is the best Video to iPod Converter for Mac OS X software for you. With the iPod Converter for Mac you can easily convert popular video formats including FLV, MPEG1, MPEG2, DivX, Xvid, WMV, 3GP, 3G2, MOV, AVI, MPEG TS/TP (for HD Video), etc to iPod compatible MPEG-4 videos. And also it is not only and iPod Converter for Mac, but it can convert all popular videos to iPhone, Apple TV, PSP, PS3, Youtube (web), Creative Zen, iRiver PMP, Archos, MP4, various mobile phones and many other digital video and audio players.MP4 Converter for Mac is an excellent Mac MP4 converter which can not only convert MP4 to MP3, WMA, AAC, WAV, etc but also convert avi, flv, wmv, mpeg, divx etc to MP4 on Mac os x to enjoy your favourite video with MP4 Converter for Mac os. Compared with other mp4 converter Mac software, the MP4 Converter for Mac provides powerful edit functions, such as setting the output settings, cropping and trimming files, merging several files into one, etc. With this MP4 Converter for Mac, you can easily convert mp4 videos to varoius format for Mac.

FLV Converter Mac is a

FLV Converter Mac is a powerful FLV Converter for Mac software which can convert FLV video files to all popular video formats and convert FLV to popular audio formats for Mac OS X users. FLV Converter Mac OS X softwrare supports all video popular formats indcluding FLV, MPG, MPEG1, MPEG2, MP4, 3GP, 3G2, MOV, AVI, Mpeg TS/TP (for HD Video), etc. The Mac FLV Converter can also convert FLV to MP3, WAV, OGG, 3GP, AAC and M4A, AC3, APE, etc audio.
How to download YouTube videos for Mac and convert the .FLV files on Mac OS? Here are the easy-to-use and top-user-rating YouTube Video Grabber Mac and Mac FLV converter tools. It is safe to install and no spyware or adware guarenteed.
With the YouTube Video Grabber Mac application, you can easily download youtube for mac and convert YouTube videos on your Mac OS. It can automatically detect the YouTube video files from the YouTube web pages you have opened and download multiple files once a time. YouTube Video Grabber Mac is a totally free download youtube videos for mac, because if you don’t want to convert downloaded videos to your mobile players, you don’t have to pay for it.

Post new comment

The content of this field is kept private and will not be shown publicly.