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

In the first part of this series, you see how ruby and python retrieve data from given URL and then parse the results using regular expression. In part two, the code is extended to query prices from  through .

  1. Specify executable
    Ruby
    #!/usr/bin/ruby
    Python
    #!/usr/bin/python
  2. Import modules
    Ruby
    require ’net/http’
    require ’rexml/document’
    Python
    import sys
    import re
    import urllib
    from xml.dom.ext.reader import Sax2
    from xml.dom.ext import Print
    from xml import xpath
  3. Validate argument
    Ruby
    if ARGV.length == 0
      puts "#{$0}: You must enter at least one argument"
      exit
    end
    Python
    if len(sys.argv) == 1:
        print "%s: You must enter at least one argument." % sys.argv[0]
        sys.exit()
  4. Initialize output and regular expressions
    Ruby
    output = ""
     
    not_in_collection_re = /class="yourEntryWouldBeHereData"/ix
    on_shelf_re = /CHECK SHELF/ix
    checked_out_re = /DUE /ix
    Python
    output = ’’
     
    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)
  5. Start loop
    Ruby
    ARGV.each do |isbn|
    Python
    for isbn in sys.argv[1:]:
  6. Validate input
    Ruby
      if not isbn.match(/[0-9xX]{10}/)
        output << "ISBN #{isbn} is invalid.\n"
        next
      end
     
      output << "ISBN: #{isbn}\n"
    Python
        if not re.match(r’[0-9xX]{10}’,isbn):
            output += ’ISBN %s is invalid.\n’ % isbn
            continue
     
        output += ’ISBN: %s\n’ % isbn
  7. Query AWS
    Ruby
      amazon_params = {’Service’ => ’AWSECommerceService’,
                       ’Operation’ => ’ItemLookup’,
                       ’AWSAccessKeyId’ => ’XXXXXXXXXXXXXXXXXXX’,
                       ’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)
    Python
        amazon_params = {
            ’Service’: ’AWSECommerceService’,
            ’Operation’: ’ItemLookup’,
            ’AWSAccessKeyId’: ’XXXXXXXXXXXXXXXXXXX’,
            ’ItemId’: isbn,
            ’ResponseGroup’: ’Medium,OfferFull’,
            ’MerchantId’: ’All’,
        }
     
        amazon_response = urllib.urlopen(’http://webservices.amazon.com/onca/xml’,urllib.urlencode(amazon_params))
  8. Parse XML
    Ruby
      xml = REXML::Document.new(amazon_response.body)
    Python
        xml = Sax2.FromXmlStream(amazon_response).documentElement
  9. Extract information from the XML
    Ruby
      new_price = xml.root.elements["Items/Item/OfferSummary/LowestNewPrice/FormattedPrice"]
      if new_price.nil?
        output << "\tNew: None available\n"
      else
        output << "\tNew: #{new_price.text}\n"
      end
     
      used_price = xml.root.elements["Items/Item/OfferSummary/LowestUsedPrice/FormattedPrice"]
      if used_price.nil?
        output << "\tUsed: None available\n"
      else
        output << "\tUsed: #{used_price.text}\n"
      end
     
      collectible_price = xml.root.elements["Items/Item/OfferSummary/LowestCollectiblePrice/FormattedPrice"]
      if collectible_price.nil?
        output << "\tCollectible: None available\n"
      else
        output << "\tCollectible: #{collectible_price.text}\n"
      end
    Python
        try:
            new_price = xpath.Evaluate(’Items/Item/OfferSummary/LowestNewPrice/FormattedPrice’,xml)[0]
            output += ’\tNew: %s\n’ % new_price.childNodes[0].nodeValue
        except:
            output += ’\tNew: None\n’
     
        try:
            used_price = xpath.Evaluate(’Items/Item/OfferSummary/LowestUsedPrice/FormattedPrice’,xml)[0]
            output += ’\tUsed: %s\n’ % used_price.childNodes[0].nodeValue
        except:
            output += ’\tUsed: None\n’
     
        try:
            collectible_price = xpath.Evaluate(’Items/Item/OfferSummary/LowestCollectiblePrice/FormattedPrice’,xml)[0]
            output += ’\tCollectible: %s\n’ % collectible_price.childNodes[0].nodeValue
        except:
            output += ’\tCollectible: None\n’
  10. Query Skokie
    Ruby
      response = Net::HTTP.get_response(’catalog.skokielibrary.info’,
                                        "/search~S4/i?SEARCH=#{isbn}")
    Python
        response = urllib.urlopen(’http://catalog.skokielibrary.info/search~S4/i’,’SEARCH=%s’ % isbn)
        body = response.read()
  11. Parse the result
    Ruby
      if not_in_collection_re.match(response.body)
        output << "ISBN #{isbn} is not in the Skokie collection.\n"
      elsif on_shelf_re.match(response.body)
        output << "ISBN #{isbn} is on the shelf.\n"
      elsif checked_out_re.match(response.body)
        output << "ISBN #{isbn} is currently checked out.\n"
      else
        output << "ISBN #{isbn} response: Unparseable!.\n"
      end
    Python
        if not_in_collection_re.search(body):
            output += ’ISBN %s is not in the Skokie collection.\n’ % isbn
        elif on_shelf_re.search(body):
            output += ’ISBN %s is on the shelf.\n’ % isbn
        elif checked_out_re.search(body):
            output += ’ISBN %s is currently checked out.\n’ % isbn
        else:
            output += ’ISBN %s response: Unparseable!\n’ % isbn
  12. End loop
    Ruby
    end
    Python
    
                    
  13. Print output
    Ruby
    puts output
    Python
    print output

Not too bad! Python can do what Ruby do but slightly longer due to too simple syntax, especially, XML APIs. Ruby comes with rexml while Python has pyxml as an external package. So choosing Ruby and Python cannot be done based on just syntax or features. It is up to you. Do you like short and compact code? Do you like clean and clear code?

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

Technorati Tags: , , , , , , , ,

Post new comment