とりあえずの独り言

テーマは特に限定せず、独り言のように

【python】適当に名前を付けると、ビルトイン関数を上書いたり、衝突したりする

python を勉強初めの時は、pythonが用意してくれてる関数を書き換えることができるっていう概念がなかったので、あれ?ってなるやつ

ビルトイン関数と同じ名前の変数を定義しちゃう

import json

print(json)
json = json.dumps({'hogehoge': 'foo'})
print(type(json))

上書きできるって概念がなくても同じ名前があると混乱するし読みづらいので、なかなかこんな書き方はしないと思うけど。。。一応

[実行結果]

<module 'json' from 'C:\\InstallDir\\Python\\Python37\\lib\\json\\__init__.py'>
<class 'str'>

json.dumpsの結果(文字列型)でjsonを上書いてしまっているので、後続でjsonモジュールの関数予防とするとobject has no attributeのエラーが出てしまう

ビルトイン関数の同じファイル名を作っちゃう

python の勉強始めたばかりだと・・・

「今日は、jsonモジュールの使い方を勉強しよっと」
jsonってファイルを試しに作ってテストするよ!」

こんな感じで、実行させようとするけど↓のようなエラーが出る

import json

json_str = json.dumps({'hogehoge': 'foo'})
print(json_str)

[エラー内容]

json_str = json.dumps({'hogehoge': 'foo'})
AttributeError: module 'json' has no attribute 'dumps'

初学者だと、本と見比べて「一字一句間違いないのに、なんでエラーが出るんだ!?」ってなるやつ これは、学習しはじめの時だとファイル名にまで意識が言ってないので気づけないことも多い気がする(自分だけかな?)

パッケージ名でも衝突する(予想外のところで)

スクレイピングするバッチを作成していて、requestsをラップしたパッケージを作ろうとして・・・

httpっていうパッケージ名をつけて、その下にclient.pyファイル内で、import requestsしたらエラーがでた

こんな感じでパッケージをつけてた
f:id:manma_shiro:20200115205955p:plain

[エラー内容]

Traceback (most recent call last):
  File "D:/Develop/euibatch/http/client.py", line 1, in <module>
    import requests
  File "D:\Develop\euibatch\venv\lib\site-packages\requests\__init__.py", line 43, in <module>
    import urllib3
  File "D:\Develop\euibatch\venv\lib\site-packages\urllib3\__init__.py", line 7, in <module>
    from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, connection_from_url
  File "D:\Develop\euibatch\venv\lib\site-packages\urllib3\connectionpool.py", line 11, in <module>
    from .exceptions import (
  File "D:\Develop\euibatch\venv\lib\site-packages\urllib3\exceptions.py", line 2, in <module>
    from .packages.six.moves.http_client import IncompleteRead as httplib_IncompleteRead
ImportError: cannot import name 'IncompleteRead' from 'http.client' (D:\Develop\euibatch\http\client.py)

ようするに、requestsモジュール内で使ってるものとhttpのモジュールが衝突したみたい

解決するにパッケージ名を衝突しない名前に変えるか、衝突しないようなトップレベルのパッケージを一つ作成してその中に配置するかって感じかな

まとめ

python 的には javaのパッケージ作成でよくみるsrc/co/jp/<プロジェクト名>みたいなつけ方するのってどうなんだろう? っと思ったけど、

qiita.com

のような記事があった。javaのように1ファイル1クラスみたいな扱いじゃないから、

  • 関連処理であるなら、多数のクラスを1ファイルにまとめる
  • それでも規模がでかくなってきたらパッケージで分割を考える
  • pythonファイルは、それ自体がjava のパッケージみたいなもの
  • pythonパッケージは、それをさらにまとめた大きなパッケージみたいなもの

割と大雑把な理解だろうけど、こんな認識でいいのかな。