試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

設定ファイルの扱いを支援するPythonのモジュールについて(shlex)

プログラムを実行する上で保存しておきたい設定があるときに、設定をファイルに保存することが多い*1のだが、その設定ファイルに対する読み込み/解析/書き込みといった処理を行うのは色々と面倒。
今回扱うPythonshlex*2というモジュールは、設定ファイルに対する読み込みと解析の部分を支援する。*3ファイルの書式としては、スペース区切り([名前] [値])やイコール区切り([名前]=[値])などが扱える。ただし、イコール区切りにしたい場合

  • 空白文字(shlexオブジェクトのメンバ変数whitespace)にイコール文字を追加
  • 空白文字のみで分割されるようにするために、メンバ変数whitespace_splitをTrueにする

という処理が必要。
(2009/2/2)whitespaceにはタブ文字が含まれているため、ファイルをタブ区切りにするとより楽に扱える。

コード例

[任意]ファイル名: shlextest.py

#! /usr/bin/python
# -*- coding: utf-8 -*-

import shlex
import sys
import os

# このソースと同じディレクトリのrcというファイルを使用
rcfile = os.path.join(os.path.dirname(__file__), 'rc')

# まとまり(トークン)を各行に表示していく
try:
  f_in = open(rcfile)
except IOError, (errno, msg):
  print >> sys.stderr, 'Cannot open file "%s": %s' % (rcfile, msg)
  sys.exit(1)
try:
  try:
    lex = shlex.shlex(f_in)
    lex.whitespace += '='        # 区切り文字にイコールを追加(必要に応じて変更)
    lex.whitespace_split = True  # 区切り文字のみで分割
    while True:
      t = lex.get_token()
      if not t:
        break
      print 'token:', t
  except IOError, (errno, msg):
    print >> sys.stderr, 'Cannot read file "%s": %s' % (rcfile, msg)
    sys.exit(1)
finally:
  f_in.close()

# 辞書に代入
try:
  f_in = open(rcfile)
except IOError, (errno, msg):
  print >> sys.stderr, 'Cannot open file "%s": %s' % (rcfile, msg)
  sys.exit(1)
try:
  try:
    lex = shlex.shlex(f_in)
    lex.whitespace += '='
    lex.whitespace_split = True
    dic = {}                 # 初期化
    while True:
      key = lex.get_token()  # 左辺
      val = lex.get_token()  # 右辺
      if not key or not val:
        break
      dic[key] = val         # 代入
  except IOError, (errno, msg):
    print >> sys.stderr, 'Cannot read file "%s": %s' % (rcfile, msg)
    sys.exit(1)
finally:
  f_in.close()
# 辞書から取り出して表示
print 'directory:', dic['directory']
print 'filename:', dic['filename']

(2010/7/11)例外に関する処理を修正

実行例

上のコードとテスト用設定ファイルを用意して実行すると下のような出力になる。

token: directory
token: /tmp/work
token: filename
token: test.dat
directory: /tmp/work
filename: test.dat

関連記事:

関連URL:

*1:直接ファイルを読み書きしないものとして、GConfや(Windowsの)レジストリのように、独自の設定データベースを読み書きする方式や、SQLiteのように、個別のファイルに書き出しつつもデータを言語によって操作する方式などがある

*2:「lex」には字句解析プログラムという意味がある

*3:書き込みに関する処理は、ファイルの書式が特に決められているわけではないこともあって用意されていない