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

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

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

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

Q&A

6回答

36304閲覧

Pythonで他のディレクトリからプログラムをimportするやり方

jimmypage0311

総合スコア22

Python

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

0グッド

4クリップ

投稿2017/02/10 03:05

編集2017/02/10 08:16

Pythonで親ディレクトリの親ディレクトリのファイルをimportしたいのですが
以下のようなコードでは, 読み込める時と読み込めない時があります。

読み込めない時と読み込めない時の例ですが
今日読み込めたのにもかかわらず、次の日に読み込めなくなるということが以下のコードでは起こります。

Python

1import sys,os 2sys.path.append('../../') # 親ディレクトリの親ディレクトリを読み込む 3 4from ... import * # ... : 親ディレクトリの親ディレクトリのフォルダ名, * : そのフォルダ内のimportしたいプログラム名

他におすすめのファイルの読み込み方法はあるでしょうか。

よろしくお願いいたします。

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

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

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

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

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

shimizukawa

2017/02/10 03:24

「読み込み」とはファイルをopen()で開くことではなく 「import したい」という意味ですよね?であれば、そのように質問を書いた方がよいです。あと、「読み込めるときと読み込めないときがある」というのは具体的に、「どうしたら、どうなった」のでしょうか?操作手順と結果を提示してください。
jimmypage0311

2017/02/10 08:26

タイトル、質問を編集いたしましたのでよろしくお願いいたします。
guest

回答6

0

sys.path をスクリプト内で調整することはあまり推奨されません。
色々なところで使いたいライブラリを置いているディレクトリが固定で、そのライブラリをimportしたいのであれば、環境変数 PYTHONPATH を設定する方法があります。

ライブラリが /path/to/pythonfiles にあるとして、今編集しているスクリプトが /path/to/pythonfiles/sub/sub/current.py だとします。

環境変数を以下のように設定します。
(Mac, Linuxの場合)

bash

1export PYTHONPATH=/path/to/pythonfiles

(Windowsの場合)

Cmd

1set PYTHONPATH=/path/to/pythonfiles

この状態でプログラムcurrent.pyを実行すれば、current.pyがどこにっても、/path/to/pythonfiles以下にあるモジュールをimportできます。このときcurrent.pyのコード上でsys.path.appendは不要です。

なお、この方法でPYTHONPATHを設定しすぎると、環境がぐちゃぐちゃになっていくので、よく分からない内は複数のパスを設定するのはやめたほうがよいと思います。

ところで、先ほど説明した方法で環境変数を設定しても、シェルを閉じるとその設定は失われてしまいます。
OS起動時に自動的にこれを設定する方法については、各OSの話になるので省略します。


蛇足ですが、以下を実行するとPythonのライブラリパス(PYTHONPATH)が確認できます。

Bash

1python -c "import sys;print(sys.path)"

普段使っている import os なども、上記で表示されるディレクトリのどこかに os.py があってそれが読み込まれているのが分かると思います。

投稿2017/02/10 08:35

shimizukawa

総合スコア1847

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

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

0

'../../'は、実行時のカレントディレクトリの親の親なので、実行時のカレントディレクトリがどこであるかによって成功したり失敗したりするんだと思います。

すでに回答がついていますが、スクリプトファイルの存在するディレクトリを基準にするように書き直す必要があります。

投稿2017/02/10 04:43

otn

総合スコア85799

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

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

0

os.pathモジュールを使うのがおすすめです。
OSごとのパスの扱いの違いを吸収してくれます。

参考(具体的な使い方):[Python]ファイル/ディレクトリ操作

投稿2017/02/10 03:11

編集2017/02/10 03:13
can110

総合スコア38339

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

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

0

相対importという手段もあります。

インポートするモジュールを指定するとき、そのモジュールの絶対名 (absolute name) を指定する必要はありません。モジュールやパッケージが他のパッケージに含まれている場合、共通のトップパッケージからそのパッケージ名を記述することなく相対インポートすることができます。 from の後に指定されるモジュールやパッケージの先頭に複数個のドットを付けることで、正確な名前を指定することなしに現在のパッケージ階層からいくつ上の階層へ行くかを指定することができます。先頭のドットが 1 つの場合、 import をおこなっているモジュールが存在する現在のパッケージを示します。 3 つのドットは 2 つ上のレベルを示します。なので、 pkg パッケージの中のモジュールで from . import mod を実行すると、 pkg.mod をインポートすることになります。 pkg.subpkg1 の中から from ..subpkg2 import mod を実行すると、 pkg.subpkg2.mod をインポートします。相対インポートの仕様は PEP 328 に含まれています。

例えば、

$ find . -name '*.py' ./pkg/subpkg1/piyo.py ./pkg/subpkg1/hoge.py ./pkg/subpkg2/fuga.py ./pkg/foo.py

というようなディレクトリ構成で、各スクリプトは

python

1# coding: utf-8 2# pkg/subpkg1/hoge.py 3 4from .piyo import * 5from ..subpkg2.fuga import * 6from ..foo import * 7

python

1# coding: utf-8 2# pkg/subpkg1/piyo.py 3 4print('Hello, piyo.') 5

python

1# coding: utf-8 2# pkg/subpkg2/fuga.py 3 4print('Hello, fuga.') 5

python

1# coding: utf-8 2# pkg/foo.py 3 4print('Hello, foo.') 5

というような内容であった場合、

python

1import pkg.subpkg1.hoge

というスクリプトを実行すると、

Hello, piyo. Hello, fuga. Hello, foo.

と、ちゃんとimportが実行されます。

ただし、注意が必要です。

まず、相対importが使えるのはモジュールの中のみです。
importされたスクリプトでないと、使えません。

例えば、上記のhoge.pyを、

python3 pkg/subpkg1/hoge.py

と直接してしてして実行すると、

Traceback (most recent call last): File "pkg/subpkg1/hoge.py", line 3, in <module> from .piyo import * SystemError: Parent module '' not loaded, cannot perform relative import

と怒られます。

あと、使えるのは「from - import」文のみで

python

1import .piyo

というようには使えません。

あと、うちのlinuxではpython2では動きません。
上記のリファレンスの説明は、Python2.7のリファレンスにも書かれているので、使えると思うんですけどねぇ…。

このようにめんどくさい点はあるのだけど、こういう記述もできる、というぐらいには知っておいてもいいかと思います。


追記:
あれ、質問文を読み直したら、既に知ってるのかな?
だとしたら余計な回答かもしれませんが、どっちとも取れるので、一応書いておきますね。

投稿2017/02/10 14:57

編集2017/02/10 15:11
katsuko

総合スコア3536

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

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

jijijiji

2017/10/05 11:33

python3で実行してみました。 一度目はうまく動くのですが、2回目以降は動作しません。 各ディレクトリに__pycache__という新規のディレクトリが作成されそのなかに__pycache__が作成されたディレクトリにある.pyファイル名の.py拡張子部分が.cpython-36.pycに変換されたものが入っています。 一旦pythonを終了してから再度pythonを立ち上げ実行するともう一度作動しますが、やはり2回目以降は何も表示されません。対策がわかればお教え下さい
guest

0

スクリプトファイルを基準にするならば、このような方法で親ディレクトリを取得できます。

python

1from os import path, pardir 2 3current_dir = path.abspath(path.dirname(__file__)) # スクリプトのディレクトリ 4parent_dir = path.abspath(path.join(current_dir, pardir)) # スクリプトの親ディレクトリ 5parent_parent_dir = path.abspath(path.join(parent_dir, pardir)) # 上記の親ディレクトリ 6 7print(current_dir) 8print(parent_dir) 9print(parent_parent_dir)

ターミナルやJupyter notebook上では上記の方法はつかえないためご注意ください。

投稿2017/02/10 03:28

driller

総合スコア720

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

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

0

sys.path.appendを呼ぶのは良い手とはいえません。
sys.pathは全てのモジュールが参照するリストですので、他のモジュールに影響を及ぼす可能性があります。
例えば、あるモジュールを外すと今まで動いていたモジュールが、途端にimport Errorが発生する、挙動が変わってしまうなどです。

私は相対インポートで解決が良いと思います。

コードを拝見すると既に相対インポートされていますが、さらにsys.path.appendしているという事は相対インポートで上手く動作していないのだと推察します。
おそらくトップレベルスクリプト(起動スクリプト)よりも上の階層のモジュールをインポートしているのではないでしょうか?
相対インポートは、トップレベルスクリプトよりも上の階層はインポートできません。

対策としては起動のためだけのスクリプトを階層の一番上に置き、今までトップスクリプトとして扱ってきたものをモジュールとしてimportしてはどうでしょうか?
これならば相対インポートで上の階層のモジュールをインポートすることができます。

投稿2017/06/01 02:31

編集2017/06/01 02:33
pashango2

総合スコア930

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問