Python ユーティリティ

このセクションでは、よくある問題を解決するために、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 マテリアルを練習するには、ログパズルの演習をご覧ください。