web-dev-qa-db-ja.com

別のフォルダからファイルをインポートする

私は次のようなフォルダ構造を持っています。

application/app/folder/file.py

file.py にある別のPythonファイルにある関数をインポートしたい

application/app2/some_folder/some_file.py

私はもう試した

from application.app.folder.file import func_name

他にもさまざまな試みがありますが、今のところ正しくインポートできませんでした。これどうやってするの?

975
Ivan

デフォルトでは、できません。ファイルをインポートするとき、Pythonは現在のディレクトリ、エントリポイントスクリプトが実行されているディレクトリ、そしてパッケージインストールディレクトリのような場所を含むsys.path(実際にはこれより少し複雑ですが、これはほとんどの場合をカバーします) ).

しかし、実行時にPythonパスに追加することができます。

# some_file.py
import sys
sys.path.insert(0, '/path/to/application/app/folder')

import file
1048
Cameron

何も問題ありません。

from application.app.folder.file import func_name

folder__init__.pyも含まれていることを確認してください。これにより、パッケージとして含めることができます。他の答えがPYTHONPATHについて話している理由はよくわかりません。

527
joey

質問のように、モジュールが平行な場所にある場合:

application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py

この短縮形は、一方のモジュールを他方から見えるようにします。

import sys
sys.path.append('../')
68
slizb

アドホックな方法は 環境変数PYTHONPATH をドキュメントに記述されているように使うことだと思います: Python2Python3

# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH

# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
42
Ax3l

最初の import sys

 import sys

2番目 フォルダパスを追加

sys.path.insert(0, '/the/folder/path/name-folder/')

3番目 あなたのサブディレクトリに__ init __.pyという名前の空のファイルを作ります(これはPythonにモジュールであることを伝えます)

  • name-file.py
    • 名前フォルダ
      • __ init __.py
      • name-module.py

4番目 フォルダ内のモジュールをインポートする

from name-folder import name-module
32
Alex Montoya

あなたの問題は、PythonがこのファイルをPythonディレクトリで探しているのに見つからないことです。自分がいるディレクトリではなく、自分がいるディレクトリについて話していることを指定する必要があります。

これを行うには、これを変更します。

from application.app.folder.file import func_name

これに:

from .application.app.folder.file import func_name

ドットを追加することで、Pythonディレクトリではなく、このフォルダでアプリケーションフォルダを探すことになります。

31
CianB

ここでの答えは明確さに欠けており、これはPython 3.6でテストされています

このフォルダ構造では:

main.py
|
---- myfolder/myfile.py

myfile.pyの内容は次のとおりです。

def myfunc():
    print('hello')

main.pyのimportステートメントは次のとおりです。

from myfolder.myfile import myfunc
myfunc()

これは hello と表示されます。

31
danday74

私が知っていることから、インポートしたい関数のフォルダーに直接__init__.pyファイルを追加してください。

27
Vaibhav Singh

あなたのpythonプロジェクトのルートディレクトリとしてapplicationを考えて、applicationappおよび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()
18
ChandanK

私のためにLinux上のpython3で働いた

import sys  
sys.path.append(pathToFolderContainingScripts)  
from scriptName import functionName #scriptName without .py extension  
17
dsg38

私は同じ課題に直面しました、特に複数のファイルをインポートするとき、私はそれをどうにかして克服しました。

import os, sys

from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))

from root_folder import file_name
14
Erick Mwazonga

これは私にはWindows上で動作します

# some_file.py on mainApp/app2 
import sys
sys.path.insert(0, sys.path[0]+'\\app2')

import some_file
12
Emeeus

Pythonの相対インポートを試してください。

from ...app.folder.file import func_name

すべての先頭のドットは、現在のディレクトリから始まる階層内の別の上位レベルです。


問題はありますか?これがうまくいかない場合は、おそらく、相対的なインポートに含まれる多くのものに噛み付いているでしょう。より詳細な回答とコメントを読む: __init__.pyを使用しても「パッケージ外の相対インポート試行」を修正する方法

ヒント:すべてのディレクトリレベルに__init__.pyがあります。最上位ディレクトリから実行するか、PYTHONPATHにその最上位ディレクトリがあるpython -m application.app2.some_folder.some_file(.pyは省略)が必要な場合があります。 あー!

12
Zectbumo

アプリケーションを他の環境に移動する場合、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 のドキュメントをチェックしてください。

12
Nagev

私は非常に特別です:私は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ネイティブ」でない場合はイベントです)

9
geekobi

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で導入され、モジュールのインポート方法をより細かく制御できるようになりました。詳しくは、資料を参照してください。

8
wecsam

特定のパスからモジュールをロードする目的がカスタムモジュールの開発中に役立つ場合は、カスタムスクリプトのルートを指すシンボリックリンクをテストスクリプトの同じフォルダに作成できます。このモジュール参照は、そのフォルダ内で実行されるスクリプトに対して同じ名前でインストールされている他のモジュールよりも優先されます。

私はこれをLinux上でテストしましたが、シンボリックリンクをサポートする最新のOSならどれでも動作するはずです。

このアプローチの利点の1つは、開発サイクルタイムを大幅に簡略化し、モジュールの異なるバージョンを管理する際の障害モードを減らすことができる、独自のローカルSVCブランチ作業コピーにあるモジュールを指定できることです。

6

私の場合は、インポートするクラスがありました。私のファイルはこんな感じでした:

# /opt/path/to/code/log_helper.py
class LogHelper:
    # stuff here

私のメインファイルには、次のコードを含めました。

path.append("/opt/path/to/code/")
from log_helper import LogHelper
2
schmudu

私はユーザーに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に等しいことが確認されました。

1
duhaime

あなたはf5を押すことによってPythonシェルをリフレッシュするか、Run - > Run Moduleに行くことができます。こうすれば、ファイルから何かを読み込むためにディレクトリを変更する必要はありません。 Pythonは自動的にディレクトリを変更します。しかし、Pythonシェルの異なるディレクトリの異なるファイルを使用したい場合は、sys、 Cameronが言ったように でディレクトリを変更できます。

1
IOstream

だから私はちょうど私のIDEを右クリックして、そして新しいfolderを追加し、そして私がそこからインポートすることができなかった理由を疑問に思いました。後で私は右クリックしてPythonパッケージを作成しなければならないことに気づきました。古典的なファイルシステムフォルダではありません。あるいは他の回答で述べられているように、__init__.py(pythonがファイルシステムフォルダをパッケージとして扱うようにする)を追加する事後の方法です。万が一誰かがこの道を進んだ場合に備えて、この答えをここに追加してください。

1
mithunpaul

Importlibを使用して、次のような文字列を使用してフォルダーからモジュールをインポートするモジュールをインポートできます。

import importlib

scriptName = 'Snake'

script = importlib.import_module('Scripts\\.%s' % scriptName)

この例には、上記のコードであるmain.pyとScriptsというフォルダーがあり、scriptName変数を変更することで、このフォルダーから必要なものを呼び出すことができます。その後、scriptを使用してこのモジュールを参照できます。 SnakeモジュールにHello()という関数がある場合、次のようにしてこの関数を実行できます。

script.Hello()

これをPython 3.6でテストしました

1
Dextron