はじめに

クローラーを開発するときにURLによって動的に関数を呼び出しをよくします。しかし、URLに https://test.com/ほげ のように2バイト文字が含まれる場合、 def ほげ(): や class ほげ(object): のようにコード上に2バイト文字を書く必要がありました。なんかかっこ悪いので本記事ではこの問題について解決した方法を書いていきます。

解決方法

Pythonはディレクトリをモジュールとして扱えるので、それを利用しました。(一応コード上ではないから…)

ディレクトリ構成

main.pyでモジュールを利用すると仮定して、parser_module以下のモジュールを動的に呼び出していきます。

スクリーンショット 2018-08-17 12.50.53.png

モジュールのコード

# parse_module/ほげ/__init__.py
from .parser import *
# parse_module/ほげ/parser.py
def parse():
    print('hoge')
# parse_module/ふが/__init__.py
from .parser import *
# parse_module/ふが/parser.py
def parse():
    print('fuga')

parser_moduleモジュールのコード

parser_module/__init__.py にkeyをモジュール名、valueをモジュールとした辞書を返す関数を定義します。

# parse_module/__init__.py
import importlib
import os
import sys

def modules():
    path = os.path.dirname(__file__)
    sys.path.append(path)
    module_name = [name for name in os.listdir(path) if os.path.isdir(os.path.join(path, name))]
    return {module.__name__: module for module in map(importlib.import_module, module_name)}

main.pyで使ってみる

parser_module/__init__.py で定義したmodules関数をインポートします。modules関数は辞書を返すので以下のように利用できます。

# main.py
from parser_module import modules


urls = [
    'https://test.com/ほげ',
    'https://test.com/ふが'
]

for path in map(lambda x: x.split('/')[-1], urls):
    modules()[path].parse()
$ python main.py
hoge
fuga

無事呼び出せました。