LoginSignup
1

More than 5 years have passed since last update.

Pythonでコマンドラインオプションでgzファイルを指定し処理

Posted at

はじめに

phpによるgzファイルの検索スクリプトを作ったことがあるが、pythonの勉強と、両者の違いと良さを確認する為に以下要件のものを作ってみる

筆者はpython入門者,phpの経験少々

なぜスクリプトが必要なのか

linuxならgrep,windowsならfindコマンドがあるのではと言われそうですが、サーバー等の運用の仕事をしていると、容易に本番環境で抽出結果をファイル保存するのは危険なのと、自由に使えるサーバがなく支給されるのはwindowsPCだけというのが現状だったりします。
そこでwindows上でgzファイルのまま対象行を検索したり解析するためのスクリプトが役立つはずです(筆者は役立った)

php経験者がpython入門してはまったところ

  • インデントが重要なこと
    • 他のプログラム熟練者でさえインデントによるステートメントの管理をしていることが衝撃だと思うらしい
    • タブインデントとスペースインデントが混ざってると怒られる
  • if分などでelseの前が空行でelseだけにコードを書くと動かない
    • 必ずコードが必要、何もしない場合はpassと記述する
if value == 'Python':
    pass
else:
    print('pythonじゃないよ')
  • bool値をfalseという風に頭文字を小文字すると怒られる
    • 本投稿とは関係ないが、falseとしたままでも怒られず、その行以降のステートメントが実行されないという事象があってなかなか気づけなかった。何故。 (centOS6.8 Python3.5)

要件

  • windowsの環境(linuxでもたぶんうごくだろうけど)
  • Python3をインストールした環境で実行
  • コマンドラインオプションで対象ファイルを指定
  • gzファイルのまま1行ずつ表示(判定・解析もやれたら)

コマンドラインオプションを利用する

ファイルの作成

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument("-f", "--file", dest="filename",help="入力ファイルを指定", metavar="FILE")
args = parser.parse_args()

print(vars(args)['filename'])

コマンドプロンプトで実行

C:\PythonScript>gzopen.py -f aa
aa

C:\PythonScript>gzopen.py -h
usage: gzopen.py [-h] [-f FILE]

Process some integers.

optional arguments:
  -h, --help            show this help message and exit
  -f FILE, --file FILE  入力ファイルを指定

phpとの違い

phpの場合getoptという関数で-fという引数の後の引数が配列に格納される

$options = getopt("f:hp::");

ベストプラクティスを知らないまま使っているだけかもしれないが、pythonのargparseと違い、デフォルトの値やヘルプ機能がない。
pythonのargparseは、デフォルト値や、ヘルプ機能が最初から用意されており、-hでヘルプを表示できるのがとても良い(以前からやりたいと思っていた)
これは素晴らしい:blush:

gzファイルを1行ずつ読み込んで標準出力

ファイルの作成

import gzip
import codecs

filename = 'gzfile.gz'
zf = gzip.open(filename,'rb')
reader = codecs.getreader("utf-16-le")
contents = reader( zf )
for line in contents:
    print(line)

phpとの違い

phpでは、下記のようなコードでgzファイルを1行ずつ取得でき、ただのテキストファイルでもそのまま処理可能。pythonではgzファイルのみのようだ。

$zh = gzopen($filename,"rb");
while (gzeof($zh) == false) {
    $line = gzgets($zh);
}

コマンドラインオプションとgzファイルを1行ずつ読み込んで標準出力を両方行う

下記の例ではunicode(UTF-16LE)のテキストファイルをgz圧縮したものを利用している

ファイルの作成

import gzip
import codecs
import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument("-f", "--file", dest="filename",help="入力ファイルを指定", metavar="FILE")
args = parser.parse_args()

filename = vars(args)['filename']


zf = gzip.open(filename,'rb')
reader = codecs.getreader("utf-16-le")
contents = reader(zf)
for line in contents:
    print(line)

UTF-8版

zf = gzip.open(filename,'rb')

reader = codecs.getreader("utf-8")
contents = reader(zf) #encodings.utf_8.StreamReader

for line in contents:
    print(line) #str

文字コードを気にしない書き方

zf = gzip.open(filename,'rt')
for line in zf:
    print(line) #str

以下でもできるようだが、いまいちしっくりこない

zf = gzip.open(filename,'rt')

line = zf.readline()
print(line)
while line:
    line = zf.readline()
    print(line)

個人的課題

windows環境だと標準出力の文字コードがcp932だとかでpython上での
文字コードの扱い方を勉強しないといけなそう。理解が深まり次第記事をアップデートする予定

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1