質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.35%
import

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

2832閲覧

Pythonのimport方法について

propg

総合スコア121

import

自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2020/07/20 07:58

Pythonでプログラムを書いていますが、自作モジュールのimport方法について、この書き方がベストなのかよく分からずにいます。

PRJ | |--bin | |--main.py | |--lib |--lib1.py |--lib2.py

上記のようなフォルダ構成で、main.pyを実行します

main.pyで、lib1, lib2のモジュールをインポートしており、以下のような書き方です。

Python

1app_home = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")) 2sys.path.append(os.path.join(app_home)) 3from lib import lib1 4from lib import lib2

PRJ配下をベースディレクトリとして指定する方法です。

この方法で問題なく動作しますが、vs code上で以下の問題があります。

  • ソースコードにPylanceがエラー表示する

Import "lib" could not be resolvedPylance (reportMissingImports)

  • ドキュメントのフォーマットを行うと、import文がファイル最上部に移動させられてしまう。sys.path.appendの前にimportすることになり、そのまま実行するとエラーになる
    => ファイル全体に対してドキュメントのフォーマットができない
  • vs.codeがモジュールパスを認識できていないのか、カーソル当てたときの説明が表示されない

質問事項

階層構造を定義したpythonプロジェクトにおいて、各階層のモジュールをimportする際のベストプラクティスはどのようにすべきでしょうか。

現在の書き方はプログラム内でライブラリパスを設定しており、正直あまりスマートには見えません。
こう書いたほうがいい。今の書き方がベストだ。などのご意見お願いします。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/07/20 08:44

binディレクトリではなくPRJディレクトリに入れることではだめなのですか?
propg

2020/07/21 00:12

特別なこだわりがあるわけではありません。 もともと参考にしたプログラムの構造がbinにメインプログラムを配置するものになっていたので同様の構造としました。 PRJ配下に置けば、そこからの相対パスとしてモジュールのimportは何の問題もなく指定することができました。
guest

回答2

0

ベストアンサー

すぐにできること

PRJ 直下に main.py を置けば、sys.path.append は必要なくなります

ベストプラクティス

プロジェクトの作り方は Python の場合、いくつかのパターンがあり、
たった一つのベストプラクティスはないようです

僕の場合は、次のようにしています

ひとつのプロジェクト内にルートパッケージをひとつだけ

ひとつのプロジェクト内には Python のルートパッケージは
ユニットテスト用の tests/ を除いてひとつだけにしてしまうと
このような問題を考える必要がなくなり、楽です

複数のパッケージを一度に開発する場合は "Editable" Installs

複数のルートパッケージを作りたい場合はディレクトリーを分け、
呼び出される側のパッケージのディレクトリー内に setup.py などを用意してパッケージ化すると
pip install できるようになります
参考: Packaging Python Projects — Python Packaging User Guide

そして、 "Editable" Installs という方法で pip install すると、
呼び出される側のパッケージを編集しても、
呼び出す側のパッケージのコードから呼び出したときに、ちゃんと変更内容が適用されます
参考: pip install — pip 20.1.1 documentation

こういうことをするときは PipenvPoetry を利用することをお奨めします
参考:
Pipenv: 人間のためのPython開発ワークフロー — pipenv 2018.11.27.dev0 ドキュメント
Poetry - Python dependency management and packaging made easy.

投稿2020/07/20 08:54

y_shinoda

総合スコア3272

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

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

propg

2020/07/21 00:19

とてもわかり易いご説明ありがとうございました。 プロジェクト直下(最上位)にメインの実行プログラムを置くのが基本だと理解しました。 実際最上位に実行プログラムを置けば、その配下のモジュールは、 import lib.lib1 だけで読み込みでき、また、vs.codeもそのモジュールを認識できていました。 私の書き方は、実行プログラムを最上位に置かない場合の特殊な書き方でした。 binとlibとすることでメインとサブを明示できて良いと思っていましたが、ルートをメインと考えればあえてbinはいらないですね。
guest

0

実行するファイルをカレントディレクトリ(IDE等で言うならプロジェクト直下のディレクトリ)に置きましょう。
以上。


滅多に使わない副スクリプトの類いは

plain

1PRJ 2| 3|--util 4| |--subcommand.py 5| 6|--lib 7 |--lib1.py

と配置して

shell

1python -m util.subcommand

-mオプションでの実行を想定する場合もあります。

その場合subcommand.pyに書くimport文は

python

1import lib.lib1

と絶対インポートになります。


本当にちゃんとするならclickのようなライブラリの助けを借りつつ、pipgitのように

shell

1python main.py sub-command --some-option some-option-arg args args args

という書式で起動するような構成まで発展するのでしょうが、そういうのはライブラリとして公開するとなった場合だけでいいと思います。

投稿2020/07/20 08:54

編集2020/07/20 08:55
quickquip

総合スコア11235

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

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

propg

2020/07/21 00:23

分かり易い回答ありがとうございました。 基本はプロジェクト直下だとわかりました。 実行時引数として指定する方法も説明いただきましたが、実行方法が複雑化するため、よほどのことでなければプロジェクト直下にルートモジュールを置いて実行するという形にしたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問