"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

TestCaseの中に「os.path.abspath(__file__)」をコピペした凡ミス/Django3.0

f:id:arakan_no_boku:20200419012754j:plain

目次

TestCaseの中に「os.path.abspath(__file__)」をコピペした凡ミス

今回は「Django」を使っている前提の話です。

僕が最近使っているフォルダ構成はこんな感じ。

functionとかmoduleを階層化して、階層をとばして結合しない縛りをいれてます。

f:id:arakan_no_boku:20200420002722p:plain

このフォルダ構成で「modules」フォルダにPythonクラスのソースを置き、そのクラスを使った処理クラスをfunctionsフォルダにおいています。

そして、tcdemo直下にそのfunctionsフォルダのクラスを使うメインのPythonプログラムを置くという構造です。

ここでUNITTESTを書く際に、settings.pyというソース内に書いている「BASE_DIR」と同じパスを取得したかったのです。

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

 僕は、これをよく考えずに

os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

の部分をコピペしてしまいました。

これが凡ミスです。

 

どのあたりが凡ミスなのか

この「__file__」は、Pythonで実行中のスクリプトファイル.pyの場所(パス)を取得するものだからです。

note.nkmk.me

だから、上記のように「module」と「functions」みたいに階層が違うところにあるソースファイルに「__file__」を書くと違うパスが返されます。

なのに、なんとなく「__file__」で返されるパスが「BASE_DIR」と同じものがかえされるような錯覚におちいってました。、

フォルダ階層が違うソースコードに、「os.path.abspath(__file__)」なんて書いて、同じパスが返されるわけがないのに・・・まさに、凡ミスです。 

 

どうすればよかったのか。

djangoには「settings.py」で定義された値を読む機能が用意されています。

それを使えばよかったのです。

例えば、BASE_DIRを使いたいなら。

from django.conf import settings

 

basedir = getattr(settings, 'BASE_DIR', None) 

ですね。

このやり方なら、どこに書こうが同じ「BASE_DIR」を取得できます。

だから。

本当なら、例えば「ja.bin」みたいなデータを静的なパスで取得したい場合なども、settings.pyの中に「JA_BIN_PATH」など独自の名前で定義して読み出せばいいです。

例えば、settings.pyで。

JA_BIN = '\\etcdemo\\functions\\modules\\ja\\ja.bin'

のように独自定義を追加しておいて。

self.basedir = getattr(settings, 'BASE_DIR', None)
self.jabin = getattr(settings, 'JA_BIN', None)
self.word2vec = wv.Word2Vec(self.basedir + self.jabin)

のように、ja.binファイルのパスを取得するとかですね。

これを、ふと忘れてコピペしてしまうのが、情けない話ではありました。

ではでは。