私は次のようなフォルダ構造を持っています。
application/app/folder/file.py
file.py にある別のPythonファイルにある関数をインポートしたい
application/app2/some_folder/some_file.py
私はもう試した
from application.app.folder.file import func_name
他にもさまざまな試みがありますが、今のところ正しくインポートできませんでした。これどうやってするの?
デフォルトでは、できません。ファイルをインポートするとき、Pythonは現在のディレクトリ、エントリポイントスクリプトが実行されているディレクトリ、そしてパッケージインストールディレクトリのような場所を含むsys.path
(実際にはこれより少し複雑ですが、これはほとんどの場合をカバーします) ).
しかし、実行時にPythonパスに追加することができます。
# some_file.py
import sys
sys.path.insert(0, '/path/to/application/app/folder')
import file
何も問題ありません。
from application.app.folder.file import func_name
folder
に__init__.py
も含まれていることを確認してください。これにより、パッケージとして含めることができます。他の答えがPYTHONPATH
について話している理由はよくわかりません。
質問のように、モジュールが平行な場所にある場合:
application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py
この短縮形は、一方のモジュールを他方から見えるようにします。
import sys
sys.path.append('../')
アドホックな方法は 環境変数PYTHONPATH
をドキュメントに記述されているように使うことだと思います: Python2 、 Python3
# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH
# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
最初の import sys
import sys
2番目 フォルダパスを追加
sys.path.insert(0, '/the/folder/path/name-folder/')
3番目 あなたのサブディレクトリに__ init __.pyという名前の空のファイルを作ります(これはPythonにモジュールであることを伝えます)
4番目 フォルダ内のモジュールをインポートする
from name-folder import name-module
あなたの問題は、PythonがこのファイルをPythonディレクトリで探しているのに見つからないことです。自分がいるディレクトリではなく、自分がいるディレクトリについて話していることを指定する必要があります。
これを行うには、これを変更します。
from application.app.folder.file import func_name
これに:
from .application.app.folder.file import func_name
ドットを追加することで、Pythonディレクトリではなく、このフォルダでアプリケーションフォルダを探すことになります。
ここでの答えは明確さに欠けており、これはPython 3.6でテストされています
このフォルダ構造では:
main.py
|
---- myfolder/myfile.py
myfile.py
の内容は次のとおりです。
def myfunc():
print('hello')
main.py
のimportステートメントは次のとおりです。
from myfolder.myfile import myfunc
myfunc()
これは hello と表示されます。
私が知っていることから、インポートしたい関数のフォルダーに直接__init__.py
ファイルを追加してください。
あなたのpythonプロジェクトのルートディレクトリとしてapplication
を考えて、application
、app
およびfolder
フォルダに空の__init__.py
ファイルを作成してください。それから、あなたのsome_file.py
の中で、func_nameの定義を得るために以下のように変更をしてください:
import sys
sys.path.insert(0, r'/from/root/directory/application')
from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file.
func_name()
私のためにLinux上のpython3で働いた
import sys
sys.path.append(pathToFolderContainingScripts)
from scriptName import functionName #scriptName without .py extension
私は同じ課題に直面しました、特に複数のファイルをインポートするとき、私はそれをどうにかして克服しました。
import os, sys
from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))
from root_folder import file_name
これは私にはWindows上で動作します
# some_file.py on mainApp/app2
import sys
sys.path.insert(0, sys.path[0]+'\\app2')
import some_file
Pythonの相対インポートを試してください。
from ...app.folder.file import func_name
すべての先頭のドットは、現在のディレクトリから始まる階層内の別の上位レベルです。
問題はありますか?これがうまくいかない場合は、おそらく、相対的なインポートに含まれる多くのものに噛み付いているでしょう。より詳細な回答とコメントを読む: __init__.pyを使用しても「パッケージ外の相対インポート試行」を修正する方法
ヒント:すべてのディレクトリレベルに__init__.py
があります。最上位ディレクトリから実行するか、PYTHONPATHにその最上位ディレクトリがあるpython -m application.app2.some_folder.some_file
(.pyは省略)が必要な場合があります。 あー!
アプリケーションを他の環境に移動する場合、sys.path.appendを絶対パスで使用するのは理想的ではありません。現在の作業ディレクトリはスクリプトの起動方法に依存するため、相対パスを使用しても必ずしもうまくいくとは限りません。
アプリケーションのフォルダ構造は固定されているので、インポートしたいモジュールのフルパスを取得するためにos.pathを使うことができます。たとえば、これが構造体の場合
/home/me/application/app2/some_folder/Vanilla.py
/home/me/application/app2/another_folder/mango.py
そして、 "mango"モジュールをインポートしたいとしましょう。 Vanilla.pyでは次のことができます。
import sys, os.path
mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
+ '/another_folder/')
sys.path.append(mango_dir)
import mango
もちろん、mango_dir変数は必要ありません。
これがどのように機能するかを理解するために、この対話型セッションの例を見てください。
>>> import os
>>> mydir = '/home/me/application/app2/some_folder'
>>> newdir = os.path.abspath(os.path.join(mydir, '..'))
>>> newdir
'/home/me/application/app2'
>>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder'
>>>
>>> newdir
'/home/me/application/app2/another_folder'
>>>
そして os.path のドキュメントをチェックしてください。
私は非常に特別です:私はWindowsでPythonを使います!
WindowsとLinuxの両方で、相対パスと絶対パスの両方がsys.path
に機能します(私のスクリプトを複数のPC上および異なるメインディレクトリで使用するため、相対パスが必要です)。
そしてWindowsを使うときは\
と/
の両方をファイル名のセパレータとして使うことができます、そしてもちろん\
をPython文字列に二重にしなければなりません、
いくつかの有効な例
sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')
(注:/
は\
よりも便利だと思います。Linuxと互換性があり、Windowsエクスプローラーへの書き込みとコピーが簡単なので、「Windowsネイティブ」でない場合はイベントです)
Python 3.4以降では、 ソースファイルから直接インポートできます(ドキュメントへのリンク) 。これは最も単純な解決策ではありませんが、私は完全性のためにこの答えを含めています。
これが一例です。まず、インポートするファイル(foo.py
):
def announce():
print("Imported!")
上記のファイルをインポートするコードは、ドキュメントの例から大きく影響を受けています。
import importlib.util
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
foo = module_from_file("foo", "/path/to/foo.py")
if __== "__main__":
print(foo)
print(dir(foo))
foo.announce()
出力:
<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
変数名、モジュール名、およびファイル名は一致する必要はありません。このコードはまだ動作します:
import importlib.util
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
baz = module_from_file("bar", "/path/to/foo.py")
if __== "__main__":
print(baz)
print(dir(baz))
baz.announce()
出力:
<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
プログラムによるモジュールのインポートはPython 3.1で導入され、モジュールのインポート方法をより細かく制御できるようになりました。詳しくは、資料を参照してください。
特定のパスからモジュールをロードする目的がカスタムモジュールの開発中に役立つ場合は、カスタムスクリプトのルートを指すシンボリックリンクをテストスクリプトの同じフォルダに作成できます。このモジュール参照は、そのフォルダ内で実行されるスクリプトに対して同じ名前でインストールされている他のモジュールよりも優先されます。
私はこれをLinux上でテストしましたが、シンボリックリンクをサポートする最新のOSならどれでも動作するはずです。
このアプローチの利点の1つは、開発サイクルタイムを大幅に簡略化し、モジュールの異なるバージョンを管理する際の障害モードを減らすことができる、独自のローカルSVCブランチ作業コピーにあるモジュールを指定できることです。
私の場合は、インポートするクラスがありました。私のファイルはこんな感じでした:
# /opt/path/to/code/log_helper.py
class LogHelper:
# stuff here
私のメインファイルには、次のコードを含めました。
path.append("/opt/path/to/code/")
from log_helper import LogHelper
私はユーザーにpip install a
を介してインストールするプロジェクトa
を次のファイルリストで作成していました。
.
├── setup.py
├── MANIFEST.in
└── a
├── __init__.py
├── a.py
└── b
├── __init__.py
└── b.py
setup.py
from setuptools import setup
setup (
name='a',
version='0.0.1',
packages=['a'],
package_data={
'a': ['b/*'],
},
)
MANIFEST.in
recursive-include b *.*
a/init。py
from __future__ import absolute_import
from a.a import cats
import a.b
a/a.py
cats = 0
a/b/init。py
from __future__ import absolute_import
from a.b.b import dogs
a/b/b.py
dogs = 1
MANIFEST.in
を含むディレクトリから次を実行して、モジュールをインストールしました。
python setup.py install
次に、ファイルシステム上のまったく異なる場所から/moustache/armwrestle
を実行できました:
import a
dir(a)
これにより、a.cats
が実際に0に等しく、a.b.dogs
が実際に1に等しいことが確認されました。
あなたはf5を押すことによってPythonシェルをリフレッシュするか、Run - > Run Moduleに行くことができます。こうすれば、ファイルから何かを読み込むためにディレクトリを変更する必要はありません。 Pythonは自動的にディレクトリを変更します。しかし、Pythonシェルの異なるディレクトリの異なるファイルを使用したい場合は、sys、 Cameronが言ったように でディレクトリを変更できます。
だから私はちょうど私のIDEを右クリックして、そして新しいfolder
を追加し、そして私がそこからインポートすることができなかった理由を疑問に思いました。後で私は右クリックしてPythonパッケージを作成しなければならないことに気づきました。古典的なファイルシステムフォルダではありません。あるいは他の回答で述べられているように、__init__.py
(pythonがファイルシステムフォルダをパッケージとして扱うようにする)を追加する事後の方法です。万が一誰かがこの道を進んだ場合に備えて、この答えをここに追加してください。
Importlibを使用して、次のような文字列を使用してフォルダーからモジュールをインポートするモジュールをインポートできます。
import importlib
scriptName = 'Snake'
script = importlib.import_module('Scripts\\.%s' % scriptName)
この例には、上記のコードであるmain.pyとScriptsというフォルダーがあり、scriptName
変数を変更することで、このフォルダーから必要なものを呼び出すことができます。その後、script
を使用してこのモジュールを参照できます。 SnakeモジュールにHello()
という関数がある場合、次のようにしてこの関数を実行できます。
script.Hello()
これをPython 3.6でテストしました