私はPython 2.5を実行しています。
これは私のフォルダツリーです:
ptdraft/
nib.py
simulations/
life/
life.py
(各フォルダーに__init__.py
もあります。読みやすくするためにここでは省略しています)
nib
モジュールの中からlife
モジュールをインポートするにはどうすればいいですか?私はそれがsys.pathに手を加えることなく行うことが可能であることを願っています。
注:実行されているメインモジュールはptdraft
フォルダーにあります。
問題は、モジュールが親ディレクトリにあること、またはそのようなことに関連していないようです。
ptdraft
を含むディレクトリをPYTHONPATHに追加する必要があります。
あなたはimport nib
があなたと一緒に働いたと言いました、それはおそらくあなたがptdraft
自身(その親ではない)をPYTHONPATHに追加したことを意味します。
相対インポート(python> = 2.5)を使うことができます。
from ... import nib
(Python 2.5の新機能)PEP 328:絶対インポートと相対インポート
_ edit _ :別のドット「。」を追加しました2つ上がる
相対インポート(from .. import mymodule
のように)はパッケージ内でのみ機能します。現在のモジュールの親ディレクトリにある 'mymodule'をインポートするには:
import os,sys,inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0,parentdir)
import mymodule
edit :__file__
属性は常に与えられるわけではありません。 os.path.abspath(__file__)
を使用する代わりに、現在のファイルのファイル名(およびパス)を取得するためにinspectモジュールを使用することをお勧めします
兄弟パッケージからのインポートに関する質問に対しても同様の回答を投稿しました。ご覧になれます こちら 。以下はPython 3.6.5、(Anaconda、conda 4.5.1)、Windows 10 machineでテストされています。 。
質問と同じフォルダ構造を想定しています
.
└── ptdraft
├── __init__.py
├── nib.py
└── simulations
├── __init__.py
└── life
├── __init__.py
└── life.py
私は.
をルートフォルダと呼び、私の場合はC:\tmp\test_imports
にあります。
setup.py
の内容は単純に
from setuptools import setup, find_packages
setup(name='myproject', version='1.0', packages=find_packages())
基本的に "any" setup.pyが動くでしょう。これはほんの最小限の例です。
仮想環境に慣れている場合は、アクティブにして次のステップに進みます。仮想環境の使用は絶対必須ではありませんが、本当に help長い目で見ればあなたは外出中です(進行中のプロジェクトが複数ある場合)。最も基本的な手順は次のとおりです(ルートフォルダで実行)。
python -m venv venv
. /venv/bin/activate
(Linux)または./venv/Scripts/activate
(Win)これについてもっと知るためには、単に "python virtual env tutorial"かそれに類似したものをグーグルで出しなさい。作成、有効化、無効化以外のコマンドは必要ないでしょう。
仮想環境を作成してアクティブにすると、コンソールから仮想環境の名前が括弧内に表示されます。
PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>
myproject
を使用して最上位パッケージpip
をインストールします。トリックはインストールをするとき-e
フラグを使うことです。これにより編集可能な状態でインストールされ、.pyファイルに加えられたすべての編集は自動的にインストールされたパッケージに含まれます。
ルートディレクトリで、次のコマンドを実行します。
pip install -e .
(ドットに注意してください、それは "現在のディレクトリ"を表します)
pip freeze
を使用してインストールされていることもわかります。
(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
mainfolder
を追加してインポートするこの例では、mainfolder
はptdraft
になります。これには、他のモジュール名(python標準ライブラリや他社製モジュールからの名前)と名前が衝突しないという利点があります。
def function_from_nib():
print('I am the return value from function_from_nib!')
from ptdraft.nib import function_from_nib
if __== '__main__':
function_from_nib()
(venv) PS C:\tmp\test_imports> python .\ptdraft\simulations\life\life.py
I am the return value from function_from_nib!
モジュールフォルダをPYTHONPATHに追加してもうまくいかない場合は、Pythonインタープリタがインポートするモジュールを検索するプログラムの sys.path リストを変更できます。 python documentation
spam という名前のモジュールがインポートされると、インタプリタはまずその名前の組み込みモジュールを探します。見つからない場合は、変数sys.pathで指定されたディレクトリのリスト内で spam.py という名前のファイルを検索します。 sys.pathは次の場所から初期化されます。
- 入力スクリプトを含むディレクトリ(または現在のディレクトリ).
- PYTHONPATH(シェル変数PATHと同じ構文のディレクトリ名のリスト)。
- インストール依存のデフォルト.
初期化後、Pythonプログラムは sys.path を変更できます。実行されているスクリプトを含むディレクトリは、標準ライブラリパスよりも先に検索パスの先頭に配置されます。つまり、ライブラリディレクトリ内の同じ名前のモジュールの代わりに、そのディレクトリ内のスクリプトが読み込まれます。置き換えが意図されていない限り、これはエラーです。
これを知って、あなたはあなたのプログラムの中で以下のことをすることができます:
import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')
# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft
sys.path にリストされている "module search path"でOS依存のパスを使うことができます。したがって、次のように簡単に親ディレクトリを追加できます。
import sys
sys.path.insert(0,'..')
親 - 親ディレクトリを追加したい場合は、
sys.path.insert(0,'../..')
Python 2についてあまり知らないでください。
python 3では、親フォルダは次のように追加することができます。
import sys
sys.path.append('..')
...そして、そこからモジュールをインポートすることができます
簡単な答えを以下に示しますので、小さくてクロスプラットフォームな仕組みを確認できます。
組み込みモジュール(os
、sys
およびinspect
)のみを使用するため、動作するはずです
Pythonはそのために設計されているため、任意のオペレーティングシステム(OS)で。
from inspect import getsourcefile
import os.path as path, sys
current_dir = path.dirname(path.abspath(getsourcefile(lambda:0)))
sys.path.insert(0, current_dir[:current_dir.rfind(path.sep)])
import my_module # Replace "my_module" here with the module name.
sys.path.pop(0)
これより少ない行については、2行目をimport os.path as path, sys, inspect
に置き換え、getsourcefile
(3行目)の先頭にinspect.
を追加し、最初の行を削除します。
-ただし、これはすべてのモジュールをインポートするため、より多くの時間、メモリ、リソースが必要になる場合があります。
from inspect import getsourcefile
import os.path
import sys
current_path = os.path.abspath(getsourcefile(lambda:0))
current_dir = os.path.dirname(current_path)
parent_dir = current_dir[:current_dir.rfind(os.path.sep)]
sys.path.insert(0, parent_dir)
import my_module # Replace "my_module" here with the module name.
Stack Overflow answerの例を使用します 現在のパスを取得する方法
Pythonで実行されたファイル?組み込みツールで実行中のコードのソース(ファイル名)を見つけます。
from inspect import getsourcefile from os.path import abspath
次に、使用するソースファイルを検索する場所で使用します。
abspath(getsourcefile(lambda:0))
私のコードは、sys.path
、pythonパスリストにファイルパスを追加します
これにより、Pythonがそのフォルダーからモジュールをインポートできるためです。
モジュールをコードにインポートした後、sys.path.pop(0)
を新しい行で実行することをお勧めします
追加されたフォルダーに、インポートされた別のモジュールと同じ名前のモジュールがある場合
プログラムの後半。他のパスではなく、インポートの前に追加されたリスト項目を削除する必要があります。
プログラムが他のモジュールをインポートしない場合、ファイルパスを削除しない方が安全です。
プログラムが終了(またはPythonシェルを再起動)した後、sys.path
に対して行った編集はすべて消えます。
私の答えは、__file__
変数を使用して実行中のファイルパス/ファイル名を取得しません
コードは、ここのユーザーがしばしばunreliableと記述しているためです。あなたはそれを使うべきではありません
他の人が使用するプログラムの親フォルダーからモジュールをインポートするための。
動作しない例( this Stack Overflowの質問からの引用):
•it できません 一部のプラットフォームで見つかりました•時々 ファイルのフルパスではありません
py2exe
には__file__
属性はありませんが、回避策がありますexecute()
を指定してIDLEから実行すると、__file__
属性はありません- OS X 10.6で
NameError: global name '__file__' is not defined
が表示されます
これがsys.pathに親ディレクトリを含むより一般的な解決策です(私のために働きます):
import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
私にとって、親ディレクトリにアクセスするための最短かつ最も好きなonelinerは、次のとおりです。
sys.path.append(os.path.dirname(os.getcwd()))
または
sys.path.insert(1, os.path.dirname(os.getcwd()))
os.getcwd()は現在の作業ディレクトリの名前を返し、os.path.dirname(directory_name)は渡されたディレクトリのディレクトリ名を返します。
実際、私の意見では、Pythonプロジェクトのアーキテクチャーは、子ディレクトリーからのモジュールが親ディレクトリーからのモジュールを使用しないようにするべきです。このようなことが起こった場合、プロジェクトツリーについて再考する価値があります。
もう1つの方法は、PYTHONPATHシステム環境変数に親ディレクトリを追加することです。
import sys sys.path.append('../')
__init__.py
ファイルがあるパッケージ環境にいないときは、pathlibライブラリ(> = Python 3.4に含まれています)はPYTHONPATHに親ディレクトリのパスを追加することを非常に簡潔で直感的にします。
import sys
from pathlib import Path
sys.path.append(str(Path('.').absolute().parent))
上記の解決策も大丈夫です。この問題に対する別の解決策は
最上位ディレクトリから何かインポートしたい場合。その後、
from ...module_name import *
また、親ディレクトリから任意のモジュールをインポートしたい場合。その後、
from ..module_name import *
また、親ディレクトリから任意のモジュールをインポートしたい場合。その後、
from ...module_name.another_module import *
これにより、必要に応じて特定のメソッドをインポートできます。
過去の答えと同じ種類のスタイル - しかしより少ない行で:P
import os,sys
parentdir = os.path.dirname(__file__)
sys.path.insert(0,parentdir)
fileは作業中の場所を返します
ライブラリを操作します。 nibという名前のライブラリを作り、setup.pyを使ってインストールし、site-packagesに入れておけば問題は解決します。あなたが作るすべてを一つのパッケージに詰める必要はありません。それをバラバラにする。
私は、スクリプトの親ディレクトリからパッケージをインポートするために、以下の方法がうまくいくことを見つけました。この例では、env.py
パッケージからapp.db
内の関数をインポートします。
.
└── my_application
└── alembic
└── env.py
└── app
├── __init__.py
└── db
import os
import sys
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)
Linuxシステムでは、 "life"フォルダからnib.pyファイルへのソフトリンクを作成できます。それから、インポートすることができます:
import nib