サブディレクトリからファイルをインポートしますか?


456

私はと呼ばれるファイル持っているtester.pyに位置し、/project

/projectには、というサブディレクトリlibがあり、次のファイルがありますBoxTime.py

/project/tester.py
/project/lib/BoxTime.py

からインポートBoxTimeしたいtester。私はこれを試しました:

import lib.BoxTime

その結果:

Traceback (most recent call last):
  File "./tester.py", line 3, in <module>
    import lib.BoxTime
ImportError: No module named lib.BoxTime

BoxTimeサブディレクトリからインポートする方法はありますか?

編集

これ__init__.pyが問題でしたが、BoxTimeとして参照するlib.BoxTimeか使用することを忘れないでください:

import lib.BoxTime as BT
...
BT.bt_function()

回答:


536

こちらのパッケージドキュメント(セクション6.4)をご覧ください:http : //docs.python.org/tutorial/modules.html

つまり、空のファイルを

__init__.py

「lib」ディレクトリ。


59
なぜハックを感じるのですか?これは、pythonが安全な/利用可能なインポートディレクトリをマークする方法です。
IAbstract 2014

7
安全/利用可能なインポートディレクトリをマークするだけでなく、ディレクトリ名をインポートするときに初期化コードを実行する方法も提供します。
Sadjad 2014年

32
はい、これはハックで汚いものです。私の意見では、ファイルシステム全体でファイルをロードする方法を言語に課すべきではありません。PHPでは、名前空間/クラスがない場合に呼び出される複数のオートローディング関数をユーザーランドコードに登録させることで問題を解決しました。その後、コミュニティがPSR-4標準を作成し、Composerがそれを実装しました。現在、誰もそれを心配する必要はありません。馬鹿げたハードコードされた__init__ファイルはありません(ただし、必要に応じて、オートロードフックを登録してください!これがhackyhackableの違いです)。
Morgan Touverey Quilling 2015

4
@AurélienOoms– import sys, os; sys.path.insert(0, os.path.abspath('..')); from sibling_package.hacks import HackyHackHack
jbowman

4
pythonは乱雑なものです:)
Jimmy Pettersson

174
  • という名前のサブディレクトリを作成しますlib
  • という名前の空のファイルを作成しますlib\__init__.py
  • lib\BoxTime.py、次のfoo()ような関数を記述します。

    def foo():
        print "foo!"
  • 上記のディレクトリのクライアントコードに、次のようlibに記述します。

    from lib import BoxTime
    BoxTime.foo()
  • クライアントコードを実行します。あなたは得るでしょう:

    foo!

ずっと後で-Linuxでは、次のようになります。

% cd ~/tmp
% mkdir lib
% touch lib/__init__.py
% cat > lib/BoxTime.py << EOF
heredoc> def foo():
heredoc>     print "foo!"
heredoc> EOF
% tree lib
lib
├── BoxTime.py
└── __init__.py

0 directories, 2 files
% python 
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from lib import BoxTime
>>> BoxTime.foo()
foo!

2
これが説明されているPythonドキュメントへのリンクを提供してもらえますか?ありがとう!
Zenon

5
そのリンクをクリック可能にしましょう:docs.python.org/3/tutorial/modules.html#packages
Gabriel Staples

パッケージを実装するための素晴らしいウォークスルーlib
MasterControlProgram '23 / 10/23

注:サブディレクトリにはダッシュやドットを含めないでください。ただし、アンダースコアは有効です。私にとっては他のシンボル名と同じ制限のように見えますが、まだドキュメントレベルまで掘り下げていません。
Alexander

underscores => python3(コメントを編集するには遅すぎます)
Alexander Stohr

68

あなたはそれを挿入してみることができますsys.path

sys.path.insert(0, './lib')
import BoxTime

11
これは、何らかの理由でinit .pyファイルを作成できない、または作成しない場合に最適です。
jpihl 14年

1
「プロジェクト」ディレクトリからpythonを実行すると機能します。「。」実行中のファイルが存在するディレクトリではなく、現在の作業ディレクトリを基準に解釈されます。あなたcd /dataと言う、python ../project/tester.py。その後、それは動作しません。
モーニングスター2014

2
これでうまくいきました。私はこれをinit .pyファイルよりも好んでいます。
Taylor Evanson、2015年

5
これははるかにうまく機能し、「正しい」ソリューションです。 init .pyは、モジュールを含む独自の子フォルダーを持つbotoのようなパッケージを台無しにします。
Dave Dopson、2015

1
あなたは(少なくとも)という名前empyファイルを作成する必要が@jpihl __init__.pyそのフォルダからPythonのimportモジュールを許可するようにします。私はその解決策を試し、完全に機能しました(v2.7.6)。
m3nda

31

libディレクトリを作成する必要があることを誰もが示唆しているようですので、私はこれを書き留めています。

サブディレクトリに名前を付ける必要はありませんlib。名前を付けることができれば、名前を付けることanythingができます__init__.py

これを行うには、Linuxシェルで次のコマンドを入力します。

$ touch anything/__init__.py 

だから今あなたはこの構造を持っています:

$ ls anything/
__init__.py
mylib.py

$ ls
main.py

その後、インポートすることができますmylibmain.py、このように:

from anything import mylib 

mylib.myfun()

次のように関数とクラスをインポートすることもできます:

from anything.mylib import MyClass
from anything.mylib import myfun

instance = MyClass()
result = myfun()

内部に配置した変数関数またはクラスに__init__.pyもアクセスできます。

import anything

print(anything.myvar)

またはこのように:

from anything import myvar

print(myvar)

マイフォルダ構造がある utils\__init__.pyutils\myfile.py。(ユーティリティには両方のファイルが含まれています)これは私がインポートしようとしている方法ですfrom utils.myfile import myMethod。しかし、私は得るModuleNotFoundError: No module named 'utils'。何が悪いのでしょうか? PS: 私は使用Djangoviews.pyていて、utilsフォルダーと同じレベルにあるインポートを試みています
Jagruti

モジュールのインポート時に絶対パスを使用してプログラムを実行することが可能ですPYTHONPATH=. python path/to/program.py
nurettin

21

libディレクトリに__init__.pyファイルが含まれていますか?

Pythonは__init__.py、ディレクトリがモジュールかどうかを判断するために使用します。


16

お試しくださいimport .lib.BoxTime。詳細については、PEP 328の相対インポートに関する説明を参照してください。


2
以前に使用された構文を見たことがないと思います。この方法を使用する強い理由はありませんか?
tgray 2009

2
なぜこれが答えではなかったのですか。もちろん、パッケージ全体を実行したい場合は、それを実行する必要があります。しかし、それは元の質問がそうであったことではありません。
Travis Griggs、2014年

これにより、ValueError:非パッケージでの相対インポートの試行
Alex

5
これは、インポート元のファイル自体がパッケージの一部である場合にのみ機能します。そうでない場合、@ Alexが指摘したエラーが表示されます。
Jonathon Reinhart

8

私はこれを基本的にすべてのケースに適用しています(__init__.pyrelative / path / to / your / lib / folderにあることを確認してください):

import sys, os
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/your/lib/folder")
import someFileNameWhichIsInTheFolder
...
somefile.foo()


例:
プロジェクトフォルダにあります:

/root/myproject/app.py

別のプロジェクトフォルダーにあります。

/root/anotherproject/utils.py
/root/anotherproject/__init__.py

そこにある/root/anotherproject/utils.pyfoo関数を使用して呼び出したい。

したがって、app.pyに次のように記述します。

import sys, os
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../anotherproject")
import utils

utils.foo()

2
使用しているos.path場合os.path.join((os.path.dirname(os.path.realpath(__file__)),'..','anotherproject')は、パスの連結で「/」をハードコーディングする代わりに使用することをお勧めします。
カウベルト

なぜあなたは単に"../anotherproject"なしで行うことができないのですos.path.dirname()か?
Moshe Rabaev

@MosheRabaev-os.path関数を使用することをお勧めします。「../anotherproject」を記述してコードをWindows OSに移動すると、コードが破損します。os.path utilsは、コードが実行されているOSを考慮して正しいパスを返す方法を知っています。詳細はdocs.python.org/2/library/os.path.html
Mercury

@MosheRabaevおよび。なしで ".."を使用dirname(realpath(__file__))すると、スクリプトの実行時に、スクリプトが存在する場所ではなく、現在の作業ディレクトリに対する相対パスが計算されます。
TJエリス

5

空のファイル__init__.pyをサブディレクトリ/ libに作成します 。メインコードの最初に追加します

from __future__ import absolute_import 

その後

import lib.BoxTime as BT
...
BT.bt_function()

以上

from lib.BoxTime import bt_function
...
bt_function()

0

これらの回答への単なる追加。

すべてのサブディレクトリからすべてのファイルをインポートする場合は、これをファイルのルートに追加できます。

import sys, os
sys.path.extend([f'./{name}' for name in os.listdir(".") if os.path.isdir(name)])

そして、これらのファイルが現在のディレクトリ内にあるかのように、サブディレクトリからファイルをインポートできます。

実施例

プロジェクトにサブディレクトリを含む次のディレクトリがある場合...

.
├── a.py
├── b.py
├── c.py
├── subdirectory_a
   ├── d.py
   └── e.py
├── subdirectory_b
   └── f.py
├── subdirectory_c
   └── g.py
└── subdirectory_d
    └── h.py

a.pyファイル内に次のコードを入れることができます

import sys, os
sys.path.extend([f'./{name}' for name in os.listdir(".") if os.path.isdir(name)])

# And then you can import files just as if these files are inside the current directory

import b
import c
import d
import e
import f
import g
import h

言い換えると、このコードはファイルがどのディレクトリから来ているかを抽象化します。


-1

/project/tester.py

/project/lib/BoxTime.py

ファイルに__init__.py到達するまで、空行のファイルを作成します

/project/lib/somefolder/BoxTime.py

#lib__init__.py-needsに#somefolderは2 つの項目が1つあり、somefolderという名前のディレクトリに は2つの項目がboxtime.pyあり、__init__.py


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.