A CLI in both

Ruby with OptionParser

The tool greets a name a number of times. Both versions take the same two flags, give the same defaults, and print one line per greeting.

require "optparse" options = { count: 1, name: "guest" } OptionParser.new do |parser| parser.on("-c", "--count N", Integer, "How many greetings") { |value| options[:count] = value } parser.on("-n", "--name NAME", "Who to greet") { |value| options[:name] = value } end.parse! options[:count].times { puts "Hello, #{options[:name]}" }

Python with argparse

import argparse parser = argparse.ArgumentParser() parser.add_argument("-c", "--count", type=int, default=1) parser.add_argument("-n", "--name", default="guest") args = parser.parse_args() for _ in range(args.count): print(f"Hello, {args.name}")

The same run in both

ruby greet.rb -c 3 -n Ada

Hello, Ada
Hello, Ada
Hello, Ada

python3 greet.py -c 3 -n Ada

Hello, Ada
Hello, Ada
Hello, Ada

Without flags both fall back to one greeting for a guest:

ruby greet.rb

Hello, guest

python3 greet.py

Hello, guest

An unknown flag shows the second difference, the exit code:

ruby greet.rb --bad

greet.rb:7:in '<main>': invalid option: --bad (OptionParser::InvalidOption)

python3 greet.py --bad

usage: greet.py [-h] [-c COUNT] [-n NAME]
greet.py: error: unrecognized arguments: --bad

Ruby exits 1 with a Ruby exception on stderr; Python exits 2 with a usage line and its own error message. A pipeline sees both as failures, but the 2 against 1 matters when a script branches on the status.

What differs

For a larger tool both languages have subcommand libraries (Ruby has optparse plus a dispatch hash, Python has argparse subparsers). The shape of the code is the same either way: parse once, validate, then call one method.

Next: Minitest against pytest

Article author: Arthur Isaev

Banner image