3262444 ランダム
 HOME | DIARY | PROFILE 【フォローする】 【ログイン】

傀儡師の館.Python

傀儡師の館.Python

【毎日開催】
15記事にいいね!で1ポイント
10秒滞在
いいね! --/--
おめでとうございます!
ミッションを達成しました。
※「ポイントを獲得する」ボタンを押すと広告が表示されます。
x

PR

Recent Posts

Calendar

Keyword Search

▼キーワード検索

Category

Archives

2023.11
2023.10
2023.09
2023.08
2023.07

Freepage List

Profile

kugutsushi

kugutsushi

Free Space

設定されていません。
2015.04.12
XML
カテゴリ:Python
以前、Python のファイル参照や操作は面倒だというあなたに path モジュール という記事を書いた。標準ライブラリの os.path はイマイチ使いにくい。

Python を使ってディレクトリやファイルをたどりながら何かするのは面倒。たとえば、このディレクトリの下のファイル名が「~」で終わっているファイルを削除したいとかいうのを書こうとすると、unix だったら find コマンドを使って、find . -name \*~ -print -exec rm {} \; とかあるわけで、そんな風にもっと簡単にできないかなぁと思う人も多いだろう。で、path モジュールを使えば、この手のものも簡単に書けるようになる。

path だと、

import path

d = '/var/apache/htdocs'
for f in d.walkfiles('*~'):
f.remove

のような書き方ができた。ちなみに、os.path (python 2) を見ると os.path.walk があるが os.path (python 3) にはない。os.walk が残っている。python 3 では、pathlib — オブジェクト指向のファイルシステムパス が追加されているが、やっぱりもっと直感的に使えるようなものが欲しい。

そこで、pyfs の登場となる。"pip install pyfs" でインストール。

import fs

target_path = /var/apache/htdocs

# 一ファイルずつ削除
for f in fs.find('*~', target_path):
fs.rm(f)


# あるいは、まとめて削除

to_delete = fs.find('*~', target_path)
fs.rmfiles( to_delete )

path や pathlib のようにファイルパスをオブジェクトとして、それを使って操作するという感じではなく、直接的に UNIX のコマンドのような感じで操作できる。ということで、気に入ってしまった。

ソースを見てみればわかるが、かなりの部分が os.path や os をラップしているだけなので、基本を覚えるのは簡単。

fs.exists(path) : os.path.exists(path)
fs.isfile(path) : os.path.isfile(path)

fs.rename(oldPath, NewPath, **kwargs) : os.rename(oldPath, newPath, **kwargs)
fs.chdir(path, **kwargs) : os.chdir(path, **kwargs)
fs.stat(path) : os.stat(path)
fs.ctime(path) : os.stat(path).st_ctime
fs.atime(path) : os.stat(path).st_atime
fs.mtime(path) : os.stat(path).st_mtime
fs.abspath(path, **kwargs) : os.path.abspath(path, **kwargs)
fs.normalize(path, **kwargs) : os.path.normpath(path, **kwargs)
fs.rm(path, **kwargs) : os.unlink(path, **kwargs)
fs.unlink(*args, **kwargs) : os.unlink(path, **kwargs)
fs.rmdir(path, recursive=True, **kwargs) : shutil.rmtree(path, **kwargs)
fs.rmfiles(paths, **kwargs) : os.unlink(path, **kwargs)
fs.exists(path, **kwargs) : os.path.exists(path, **kwargs)
fs.cwd() : os.getcwd()
fs.basename(path, ext="") : os.path.basename(path).replace(ext, "")
fs.dirname(path) : os.path.dirname(path)
fs.sep : os.path.sep

これらに加えて、

fs.truncate(path, **kwargs) : path 以下のすべてのファイルとディレクトリを削除
fs.rmdir(path, recursive=True, **kwargs) : path のディレクトリを削除
(再帰的に削除は、recursive=True を指定。
os.rmdir か os.rmtree で削除している)
fs.rmfiles(paths, **kwargs) : リストで渡されたファイルを削除
fs.rmdirs(paths, **kwargs) : リストで渡されたディレクトリを削除
fs.mkdir(path, recursive=True, **kwargs) : Unix コマンドの mkdir と同じ。
recursive=True で、mkdirs
fs.touch(path) : Unix のタッチコマンドと同じ。
fs.list(path='.') : os.listdir(path) の結果を isfile してファイルだけ残して、
iterable にしている。
fs.listdirs(path='.') : os.listdir(path) の結果を isdir してディレクトリだけ残して
iterable にしている。
fs.find(pattern, path='.', exclude=None, recursive=True) : パターンに指定されたファイルを
iterable に返す。
exclude で除外ディレクトリも指定できる。再帰的適応も可。
os.walk で走査して、fnmatch.filter でフィルタしている。
fs.finddirs(pattern, path='.', exclude=None, recursive=True) : find のディレクトリ版。
fs.join(*args, **kwargs) : os.path.join(*args, **kwargs) と同じ。
+リストで引数を渡すことができる。
fs.extname(path, **kwargs) : name, ext = os.path.splitext(path, **kwargs) の ext を返す。
fs.open(path, mode='r', **kwargs) : 標準の open(path, mode, **kwargs)
fs.write(path, content, encoding="UTF-8", append=False, raw=False) : 標準の open を使って
エンコード指定で書き込む。
fs.read(path, encoding="UTF-8") : 標準の open を使って、エンコード指定で読み込む。
fs.append(*args, **kwargs) : fs.write(*args, append=True, **kwargs)
fs.get(*args, **kwargs) : fs.read(*args, **kwargs)
fs.put(*args, **kwargs) : fs.write(*args, **kwargs)
fs.filename(*args, **kwargs) : fs.basename(*args, **kwargs)
fs.extension(*args, **kwargs) : fs.extname(*args, **kwargs)

要するに、

a pythonic file system wrapper for humans

An easy to use file system wrapper for Python that aims to simplify os, os.path, os.walk, shutils, fnmatch, etc

ということ。

サンプルを少し見てみる。

*.xls か、*.xlsx を探してきて何かしたい。

for filename in fs.find(['*.xls', '*.xlsx']):
pass

config ディレクトリにある *.ini ファイルを local_* 以外取り出して何かしたい。

for filename in fs.find('*.ini', path='config', exclude='local_*'):
pass

Vagrantfile を config ディレクトリから探して何かしたい。見つからなければ None。

filename = next( fs.find('Vagrantfile', path='config'), None)

backup ディレクトリにある *.sql のうち最新のアクセス時刻があるファイルを取り出して何かしたい。

filename = max( fs.find('*.sql', path='backup'), key=fs.ctime)

.git ディレクトリを見つけて削除したい。

for dir in fs.finddirs('.git'):
fs.truncate(dir)

なくても困らないけど、あれば、便利で、書くコードが短くて済むし、可読性もよくなるので、ちょっとツールを作るときに重宝すると思う。





お気に入りの記事を「いいね!」で応援しよう

Last updated  2015.04.13 03:14:29
コメント(0) | コメントを書く


■コメント

お名前
タイトル
メッセージ
画像認証
別の画像を表示
上の画像で表示されている数字を入力して下さい。


利用規約に同意してコメントを
※コメントに関するよくある質問は、こちらをご確認ください。



© Rakuten Group, Inc.