このセクションでは、よくある問題を解決するために、Python の多くの標準ユーティリティ モジュールをいくつか取り上げます。
ファイル システム -- os、os.path、wiper
*os* モジュールと *os.path* モジュールには、ファイル システムとやり取りするための多くの関数が含まれています。*shutil* モジュールはファイルをコピーできます。
- os モジュールのドキュメント
- filenames = os.listdir(dir) -- そのディレクトリ パス内のファイル名のリスト(.ファイル名は絶対パスではなく、ディレクトリ内の名前です。
- os.path.join(dir, filename) -- 上記のリストのファイル名が指定された場合、これを使用して dir とファイル名をまとめ、パスを作成します
- os.path.abspath(path) -- パスを指定すると、絶対形式を返す(例: /home/nick/foo/bar.html)
- os.path.dirname(path), os.path.basename(path) -- dir/foo/bar.html を指定し、ディレクトリ名「dir/foo」とベース名「bar.html」を返す
- os.path.exists(path) -- 存在する場合は true
- os.mkdir(dir_path) -- 1 つのディレクトリを作成します。os.makedirs(dir_path) は、このパスに必要なすべてのディレクトリを作成します。
- actil.copy(source-path, dest-path) -- ファイルのコピー(宛先のパスのディレクトリが存在している必要があります)
## Example pulls filenames from a dir, prints their relative and absolute paths def printdir(dir): filenames = os.listdir(dir) for filename in filenames: print(filename) ## foo.txt print(os.path.join(dir, filename)) ## dir/foo.txt (relative to current dir) print(os.path.abspath(os.path.join(dir, filename))) ## /home/nick/dir/foo.txt
モジュールの確認は、組み込みの Python help() 関数と dir() 関数で適切に動作します。インタープリタで「import os」を行い、その後、コマンド dir(os)、help(os.listdir)、dir(os.path)、 help(os.path.dirname) を使用して、モジュールで利用できるものを確認します。
外部プロセスの実行 -- サブプロセス
「subprocess」モジュールを使用すると、簡単に外部コマンドを実行してその出力を取得できます。
- サブプロセス モジュールのドキュメント
- output = subprocess.check_output(cmd, stderr=subprocess.STDOUT) -- コマンドを実行し、終了するまで待ってから、出力テキストを返します。このコマンドは、標準出力と標準エラーが 1 つの出力テキストに組み合わされた状態で実行されます。失敗した場合は CalledProcessError がスローされます。
- サブプロセスの実行をより詳細に制御したい場合は、subprocess.popen クラスを参照してください。
- 簡単な subprocess.call(cmd) もあります。これはコマンドを実行して出力を出力にダンプし、エラーコードを返します。コマンドを実行したくても、コマンドの出力を Python データ構造にキャプチャする必要がない場合は、この方法が機能します。
import subprocess ## Given a dir path, run an external 'ls -l' on it -- ## shows how to call an external program def listdir(dir): cmd = 'ls -l ' + dir print("Command to run:", cmd) ## good to debug cmd before actually running it (status, output) = subprocess.getstatusoutput(cmd) if status: ## Error case, print the command's output to stderr and exit sys.stderr.write(output) sys.exit(status) print(output) ## Otherwise do something with the command's output
例外
例外は、特定の行で通常の実行を停止してエラー処理コードに制御を移行するランタイム エラーを表します。このセクションでは、例外の最も基本的な使用例のみを紹介します。たとえば、ランタイム エラーは、プログラムで使用される変数に値がない(ValueError .. これが数回見られたことでしょう)、ファイルが存在しないことによるファイル オープン操作エラー(IOError)です。詳しくは、例外のチュートリアルと例外リスト全体をご覧ください。
これまで説明してきたように、エラー処理コードがない場合、ランタイム例外が発生するとプログラムはエラー メッセージとともに停止します。これは適切なデフォルト設定であり、何度も目にしています。次のように、コードに「try/exception」構造を追加することで、例外を処理できます。
try: ## Either of these two lines could throw an IOError, say ## if the file does not exist or the read() encounters a low level error. f = open(filename, 'rb') data = f.read() f.close() except IOError: ## Control jumps directly to here if any of the above lines throws IOError. sys.stderr.write('problem reading:' + filename) ## In any case, the code then continues with the line after the try/except
try: セクションに、例外をスローする可能性のあるコードが含まれています。before: セクションには、例外が発生した場合に実行するコードが格納されます。例外がない場合、exception: セクションはスキップされます(つまり、このコードはエラー処理のみを目的としており、コードの「通常」のケースではありません)。「exceptions IOError as e: ..」を使用すると、例外オブジェクト自体へのポインタを取得できます(e は例外オブジェクトを指します)。
HTTP -- urllib と urlparse
モジュール *urllib.request* は、URL 取得機能を提供します。これにより、URL を読み取り可能なファイルのように見せることができます。*urlparse* モジュールは、URL を分解して 1 つにまとめることができます。
- urllib.request モジュールのドキュメント
- ufile = urllib.request.urlopen(url) -- その URL のオブジェクトのようなファイルを返します
- text = ufile.read() -- ファイルのように読み取ることができる(readlines() なども可能)
- info = ufile.info() -- そのリクエストのメタ情報。info.gettype() は MIME タイプ(例: text/html)です。
- baseurl = ufile.geturl() -- リクエストの「ベース」URL を取得。リダイレクトのため、元の URL とは異なる場合があります。
- urllib.request.urlretrieve(url, filename) -- 指定されたファイルパスに URL データをダウンロードします
- urllib.parse.urljoin(baseurl, url) -- フル URL の場合もあれば、フルでない URL と、元のページのベース URL を指定すると、完全な URL を返します。上記の geturl() を使用してベース URL を指定します。
すべての例外は urllib.error に含まれます。
from urllib.request import urlopen ## Given a url, try to retrieve it. If it's text/html, ## print its base url and its text. def wget(url): ufile = urlopen(url) ## get file-like object for url info = ufile.info() ## meta-info about the url content if info.get_content_type() == 'text/html': print('base url:' + ufile.geturl()) text = ufile.read() ## read all its text print(text)
上記のコードは適切に機能しますが、なんらかの理由で URL が機能しない場合のエラー処理は含まれていません。次に示すのは、URL オペレーションが失敗したときにエラー メッセージを出力する try/exception ロジックを追加する関数のバージョンです。
urlopen()
がハングアップしているように見える場合は、システムによって一部の HTTP アドレスへの直接アクセスが許可されていない可能性があります。wget
または curl
を使用して同じ URL を取得してみることで、これを確認できます。これらのプログラムも失敗した場合は、プロキシ サービス経由で HTTP コンテンツを取得する必要があります。プロキシ アクセスの構成については、このチュートリアルでは説明しません。
## Version that uses try/except to print an error message if the ## urlopen() fails. def wget2(url): try: ufile = urlopen(url) if ufile.info().get_content_type() == 'text/html': print(ufile.read()) except IOError: print('problem reading url:', url)
演習
ファイル システムと外部コマンドの資料を練習するには、コピーの特殊演習をご覧ください。urllib マテリアルを練習するには、ログパズルの演習をご覧ください。