ruby/python จัดการ command line arguments

มี server นึง (เขียนด้วย C/C++) ในบริษัทผมที่ผมต้องใช้งาน ต้องขอข้อมูลจากมันเป็นประจำ การที่จะเอา software เต็มๆ ไปขอข้อมูลจากมันบางทีก็เป็นเรื่องยุ่งยาก เขาก็เลยมีตัว test connection (เขียนด้วย C/C++ เช่นกัน) ไว้ทดสอบขอข้อมูลจาก server ตัวนั้นเพื่อดูว่ามันได้ข้อมูลไหม หรือเราลงถูกรึเปล่า ทีนี้ไอ้ตัว simple tool ตัวนี้มันใช้ยากพอดูเลย

$> ./runaction -s <server service> -h <server IP/Host> -e <encryption ไหม ตอบได้ yes/no> -p <server port> -f <file ใส่ชื่อ item ที่จะขอ>

จะเห็นว่าชื่อ parameter มันยาก แถมผมต้อง save ชื่อ item ที่จะขอลง file ถ้าจะขอหลาย item ก็ต้องเคาะบรรดทัดไปเรื่อยๆ แบบนี้

$> cat item.txt
facebook
oracle
ibm

แล้วก็ต้องใส่ item.txt ลงไปใน -f ข้างบน แล้ว server ก็จะส่งข้อมูลของ facebook, oracle และ ibm มาให้ แถมยังต้องใส่ env variable “ACTION_PATH” ไปที่ folder ของตัว simple tool นั้นอีก

ที่นี้ผมมีเรื่องที่จะต้องเปลี่ยน item บ่อยๆ เพื่อทดสอบอะไรบางอย่าง เลยอยากจะให้ใส่ชื่อ item ลงใน command เลยไม่ต้องไปสร้าง file เอง แถมทดสอบกับ server เดียวกันซ้ำๆ ก็ใส่ค่า default ไปเลย สรุป requirement ได้ดังนี้

  • ผมใส่ชื่อ item เป็น facebook,apple,vodaphone แล้วมันไปสร้าง file ชื่อ item ให้
  • มี default host, service, port, encryption ผมไม่จำเป็นต้องใส่ถ้าต่อกับ default server แต่ถ้าผมจะต่อกับ server ตัวอื่น ก็ต้องใส่ parameter อะไรไปในรูปแบบที่ง่ายกว่านี้
  • เฉพาะ item เป็น field ที่ต้องใส่เสมอ


จาก Requirement ข้างบน เลยเขียน script ง่อยๆ มาครอบ เริ่มที่ python ที่ผมถนัดโดยใช้ Argparse ที่เนยซดแนะนำ

#!/usr/local/bin/python

import os
import sys
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--host',help='input Host IP [optional]',type=str, default='127.0.0.1')
parser.add_argument('--service',help='input Host Service [optional]',type=str, default='ABC')
parser.add_argument('--port',help='input Host Port [optional]',type=str, default='8880')
parser.add_argument('--encrypt',help='input Host encryption [optional]',type=str,choices=['yes','no'],default='yes')
parser.add_argument('item',type=str)
args = parser.parse_args()

ric_file = './tmp_item.txt'
addN = lambda value: '%s\n'%(str(value))

with open(ric_file,'w') as foutput:
	for ric in args.item.split(','):
		foutput.write(addN(ric))

strCMD=""
os.putenv("ACTION_PATH","/home/ply/software/action")
strCMD='./runaction -s %s -h %s -e %s -p %s -f %s '%(args.service,args.host,args.encrypt,args.port,ric_file)

print strCMD
os.system(strCMD)

ข้อสังเกตุ

  • lambda addN นี่โผล่มาใน version แรกที่รองรับแค่ item เดียวเพราะถ้าไอ้ text file ไม่ตบบรรทัดใหม่ให้ tool แม่งเจ๊ง -*- ตอนนี้เลยไม่รู้ว่าต้องใส่รึเปล่า
  • จริงๆ ลองใช้ parser.add_argument(‘item’,nargs=”*”) แล้วจะได้ array [“item1″,”item2″,”item3”,…] เลยแต่มันรองรับแค่ space delimeter แบบ facebook ibm intel เท่านั้น ใช้ลูกน้ำไม่ได้ เลยย้อนกลับมาสั่ง split แม่ม

อีกภาษานึงที่ผมพยายามหัดมานานมากกกแล้วแต่ยังเขียนไม่เป็นสักทีคือ ruby ก็เลยลองเขียน code ข้างบนด้วย ruby กับ OptionParser logic ก็ลอกมาง่ายๆ เพราะมันตรงไปตรงมาอยู่แล้ว

#!/usr/local/bin/ruby
require 'optparse'

options={:host=>'127.0.0.1',:service=>'ABC',:port=>'8880',:encrpyt=>'yes',:file=>[]}

optparse = OptionParser.new do |opts|
	opts.banner = "Usage: simple.rb [options]"
	opts.separator ","
	opts.on("--host host","input Host IP [optional]") { |host| options[:host]=host }
	opts.on("--service service","input Host Service [optional]") { |service| options[:service]=service }
	opts.on("--port port","input Host Port [optional]") { |port| options[:port]=port }
	opts.on("--protocol OPT",[:yes,:no],"'input Host encrypt [optional]") do |encrpyt| 
		options[:encrpyt]=encrpyt
	end
	opts.on("-f a,b,c",Array,"Input Items name") { |f| options[:file]=f }
end.parse!

ric_file = './tmp_item.txt'
File.open(ric_file,'w') do |file|
	options[:file].each { |ric| file.puts ric }
end

ENV['ACTION_PATH']='/home/ply/software/action'
strCMD = "./runaction -s #{options[:service]} -h #{options[:host]} -e #{options[:encrpyt]} -p #{options[:port]} -f #{ric_file}"

exec(strCMD)

ข้อสังเกตุ

  • ส่วนตัวคิดว่า argparse ใน python ใช้ง่ายกว่า ruby optparse แต่ optparse ก็ทำให้ผมรับข้อมูลมาเป็น array ได้ตรงไปตรงมากว่า
  • optparse บน windows แม่งรับ array ไม่ได้ ไปลองบน linux แล้ว work -*-
  • วิธีที่ ruby จะรับ shell command มี 4 วิธี แต่ผมลองแล้ว work แค่ exec แฮะ
  • ยังหาวิธีทำ require argument ไม่ได้ -*- ต้องหาทางกันต่อไป

และแล้วชีวิตผมก็ง่ายขึ้นมาระดับนึงอ่ะนะ

Categories: Code, Tech | Tags: , , , , , , | 1 Comment

Post navigation

One thought on “ruby/python จัดการ command line arguments

  1. Reblogged this on veer.

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

Create a free website or blog at WordPress.com.

Bomreview

โบ้มรีวิว โตแล้วจะรีวิวอะไรก็ได้

rerng.rak

Just another WordPress.com weblog

neizod

Smile! You’re at the best WordPress.com site ever

Admod's blog

just logs

freeclub

พยายามเขียนให้ยาวกว่าเฮดเดอร์ข้างบนจะได้ดูสวยๆ

Anontawong's Musings

a daily dose of a new perspective

TravelKanuman

Travel around the world

kemisara

Belle Kemisara Paladesh's Fan Site - เว็บไซต์แฟนคลับเบลล์ เขมิศรา พลเดช

eatandysummers

eat. travel. live.

Jonathan Fleming's Blog

A Photography Blog

Viewfinder - Street Photography Blog

Jimmy Yang Street Photography Blog

PinkiiGirl

Be one of those who change things and push the human race forward

บล็อกอะไรไม่รู้ของแบม

Ordinary guy blogging about comic books, video games, movies and stuffs.

Pawoot Personal Blog & Think Tank

E-Business Man Daily Life and What I'm Thinking

Mahalarp

journeys & musics never ended ...

Tyson Robichaud Photo-blography

Tips, tricks, reviews and general rambling.

%d bloggers like this: