🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2277閲覧

Python での自作パッケージのインポート

Yhaya

総合スコア439

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/11/01 14:51

環境

  • Ubuntu 19.10
  • python 3.7.3

生じている問題

別フォルダに分けた関数をインポートしようとすると ModuleNotFoundError が出てしまいます。

今、私が作業しているディレクトリは下のようになっています。

bash

1UNet 2├── README.md 3├── __init__.py 4├── model.py 5├── prediction.py 6├── prepare_data.py 7├── tests 8│   ├── test_model.py 9│   ├── test_prepare_data.py 10│   └── test_train.py 11└── train.py

pythonを実行しているのは UNet の親ディレクトリからで、python ./UNet/train.py というように呼び出しています。ここで、train.py の中では、

python

1import argparse 2import tensorflow as tf 3import tensorflow.keras.backend as K 4from UNet import model # エラー 5from UNet.prepare_data import data_gen # エラー 6import os

のように model.py と prepare_data.py をインポートしていますがここで ModuleNotFoundError: No module named "UNet" というエラーが出てしまいます。

どうすれば正常にインポートできるでしょうか?よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

よくある質問です。
(しかし、結構分かりづらい話です)

過去の自分の回答です。

起動スクリプトの下にパッケージ(ディレクトリ)を作り、それ以外のスクリプトはそのパッケージ以下に配置し、お互いを相対importでインポートするのが好ましいと思います。

今回の場合は、例えば「train.py」の中身が

python

1import argparse 2import tensorflow as tf 3import tensorflow.keras.backend as K 4from UNet import model 5from UNet.prepare_data import data_gen 6import os 7 8# ... 9 10if __name__ == '__main__': 11 parser = argparse.ArgumentParser() 12 # ...

となっているとしたら、以下のようにします。

python

1import tensorflow as tf 2import tensorflow.keras.backend as K 3from . import model 4from .prepare_data import data_gen 5import os 6 7# ... 8
  • if __name__ == '__main__':」以下の処理は、train.pyから外す。
  • UNet以下のモジュールへのimportは、相対importで行う。(これは、UNet以下全てのモジュールに共通する事)

そして、「UNet」と同じディレクトリに起動スクリプトを作り、先にtrain.pyから外した処理を記述します。

python

1import argparse 2import UNet.train 3 4if __name__ == '__main__': 5 parser = argparse.ArgumentParser() 6 # ... 7

ちなみに、tests ディレクトリは配置上上のディレクトリをインポートする必要があるのですが、例えばtestsから一つ上の train.py をインポートするにはどうするのが正しいのでしょう?

例えばtests/test_train.pyからtrain.pyをimportするのであれば、

python

1# UNet/tests/test_train.py 2 3from .. import train

です。
「.」を重ねる事によって、一階層上のディレクトリを参照します。

投稿2019/11/01 15:17

編集2019/11/02 01:48
katsuko

総合スコア3536

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Yhaya

2019/11/02 01:15

ありがとうございます。ちなみに、tests ディレクトリは配置上上のディレクトリをインポートする必要があるのですが、例えばtestsから一つ上の train.py をインポートするにはどうするのが正しいのでしょう?
katsuko

2019/11/02 01:48

回答に追記しました。
Yhaya

2019/11/02 05:16

from .. import train とすると「ValueError: attempted relative import beyond top-level package 」というエラーが出るのですが、これはどういうことでしょうか?
katsuko

2019/11/02 06:31

「tests/test_train.py」と「train.py」が同じトップレベルパッケージの下にない(なので、トップレベルを超えている)というメッセージです。 私の回答の通り、起動スクリプト(最初に実行するスクリプト)を「UNet」と同じところに置いて実行していればそのようなエラーは起きないはずですが、その辺りはどうですか。
Yhaya

2019/11/02 07:07

UNet と同じディレクトリに testsディレクトリを移し、「from ..UNet import train」としてUNetとtestsディレクトリの親ディレクトリから「python -m pytest tests/test_train.py」を実行したところ「E ImportError: attempted relative import with no known parent package」となりました。
katsuko

2019/11/02 12:36

UNetと同じディレクトリに置いたら、もう同じトップレベルとは言えないので相対importは使えません。 「from UNet import train」としてください。
Yhaya

2019/11/02 14:12

そうすると最初の質問の問題に戻ってしまうんですよね。。。 すみません、長くなりすぎてしまって最初の質問から広がりすぎてしまっている気がしてきたので、新しく質問立てました。もしよろしければそちらもお願いいたします。ありがとうございました。 https://teratail.com/questions/220907?modal=q-comp
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問