2015/10/29

Python Tips:カレントユーザのホームディレクトリのパスを取得したい

Python でカレントユーザのホームディレクトリのパスを取得する方法をご紹介します。

Python でカレントユーザのホームディレクトリを取得するには os.path.expanduser() 関数を使うのが便利です。

import os.path

print(os.path.expanduser('~'))  
# => /Users/ユーザー名

print(os.path.expanduser('~/.bashrc'))
# => /Users/ユーザー名/.bashrc

公式のドキュメントには以下のように説明されています。

On Unix, an initial ~ is replaced by the environment variable HOME if it is set; otherwise the current user’s home directory is looked up in the password directory through the built-in module pwd. An initial ~user is looked up directly in the password directory.

On Windows, HOME and USERPROFILE will be used if set, otherwise a combination of HOMEPATH and HOMEDRIVE will be used. An initial ~user is handled by stripping the last directory component from the created user path derived above.

Unix では、先頭の ~ は、環境変数 HOME が設定されているならその値に置き換えられます。そうでなければ、現在のユーザのホームディレクトリをビルトインモジュール pwd を使ってパスワードディレクトリから探して置き換えます。先頭の ~user については、直接パスワードディレクトリから探します。

Windows では ~ だけがサポートされ、環境変数 HOME または HOMEDRIVE と HOMEPATH の組み合わせで置き換えられます。

便利ですねー。


参考
linux - How to find the real user home directory using python? - Stack Overflow
10.1. os.path — Common pathname manipulations — Python 2.7.10 documentation
10.1. os.path — 共通のパス名操作 — Python 2.7ja1 documentation

2015/10/26

Python Tips:Python でゼロパディングしたい

今回は Python でゼロパディングする方法をご紹介します。

  • 1. int の場合
  • 2. str の場合


1. int の場合


整数型の場合は string 型の format() メソッドや % 演算子を使う方法が最もシンプルかと思います。

format() メソッド:

number = 50
number_padded = '{0:04d}'.format(number)
print(number_padded)  # => '0050'

% 演算子:

number = 50
number_padded = '%04d' % number
print(number_padded)  # => '0050'

いずれも 04d で「 4 桁よりも短い場合はゼロパディングで 4 桁にする」という意味になります。もともとの数値が 4 桁よりも長い場合にはゼロパディングやトリムなどは行われません。

いずれの場合も 0 ではなく半角空白で詰めたい場合には 04d のところを 4d に変えれば OK です。

2. str の場合


文字列の場合にはそのままずばりなメソッド zfill() というものが用意されています。名前の zfill は「ゼロフィル」の略かと思います。

number_string = '50'  
number_padded = number_string.zfill(4)
print(number_padded)  # => '0050'

文字列の場合は zfill() の他にも同等のメソッドがいくつか用意されています。

# rjust() は元の文字列を右づめで入れて引数で指定された長さまで文字で埋める
number_string = '50'
print(number_string.rjust(8, 'V'))  # => 'VVVVVV50'

# rjust() は元の文字列を左づめで入れて引数で指定された長さまで文字で埋める
number_string = '50'
print(number_string.ljust(8, 'V'))  # => '50VVVVVV'

# rjust() は元の文字列を左づめで入れて引数で指定された長さまで文字で埋める
number_string = '50'
print(number_string.ljust(8, 'V'))  # => '50VVVVVV'

# center() は元の文字列を中央寄せにして、引数で指定された長さになるよう指定された文字を両端に入れる
number_string = '50'
print(number_string.center(8, 'V'))  # => 'VVV50VVV'

以上です。

直感的でわかりやすい API で気持ちがいいですね。

参考
python - Nicest way to pad zeroes to string - Stack Overflow

2015/10/14

Python Tips:関数の定義を調べたい

Python の関数がどのように宣言・定義されているのかを調べる方法をご紹介します。

名前そのままの inspect.getsource 関数を使うと、関数のソースコードを確認することができます。

import inspect

# requests の get 関数を調べる
import requests
inspect.getsource(requests.get)
# =>
#   def get(url, **kwargs):
#       """Sends a GET request.
# 
#       :param url: URL for the new :class:`Request` object.
#       :param \*\*kwargs: Optional arguments that ``request`` takes.
#       :return: :class:`Response ` object
#       :rtype: requests.Response
#       """
# 
#       kwargs.setdefault('allow_redirects', True)
#       return request('get', url, **kwargs)
# 


ドキュメントがいまいちわかりづらい場合なんかには、直接ソースを見にいくよりはこちらの方法で確認した方が手軽で素早いのではないでしょうか。

2015/10/06

Python Tips:zip ファイルをインターネットからダウンロードして利用したい

今回は Pyhton で zip ファイルをインターネットからダウンロードして利用する方法をご紹介したいと思います。

ダウンロードの部分は Python を代表する requests ライブラリ、 zip ファイルの取り扱いの部分は標準ライブラリの zipfile を使う方法がおすすめです。

import requests
import zipfile

まずはダウンロードから見てみましょう。

import requests

# @see http://stackoverflow.com/questions/16694907/how-to-download-large-file-in-python-with-requests-py

def download_file(url):
    """URL を指定してカレントディレクトリにファイルをダウンロードする
    """
    filename = url.split('/')[-1]
    r = requests.get(url, stream=True)
    with open(filename, 'wb') as f:
        for chunk in r.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                f.flush()
        return filename
    
    # ファイルが開けなかった場合は False を返す
    return False

ファイルサイズが大きくてもいいようにするには requests.get の steam オプションや iter_content などを使います。このコードはほぼ丸々上記 URL の Stack Overflow のところのものを使っています。

以下のようなコードで動作確認することができます。

if __name__ == "__main__":
    # 郵便局の郵便番号データをダウンロード
    url = 'http://www.post.japanpost.jp/zipcode/dl/kogaki/zip/ken_all.zip'
    filename = download_file(url)
    if filename:
        print('{} is downloaded.'.format(filename))

つづいて zip ファイルを扱う部分を。こちらは zipfile が提供するクラスと関数を使えばわずか数行です。

import zipfile

def zip_extract(filename):
    """ファイル名を指定して zip ファイルをカレントディレクトリに展開する
    """
    target_directory = '.'
    zfile = zipfile.ZipFile(filename)
    zfile.extractall(target_directory)

こちらも確認してみましょう。

if __name__ == "__main__":
    # 郵便局の郵便番号データをダウンロード
    filename = 'ken_all.zip'
    zip_extract(filename)

問題なく動作することが確認できたら、これらをつなぐとよいでしょう。

あとは展開されたファイルを好きなように利用すれば OK です。便利ですねー。