0

次のようなフォルダー構造を持つpython 2.6 Djangoアプリがあります。

/foo/bar/__init__.py

次のようなPythonモジュールでいっぱいのファイルシステムに、別のいくつかのディレクトリがあります。

/modules/__init__.py
/modules/module1/__init__.py
/other_modules/module2/__init__.py
/other_modules/module2/file.py

各モジュール__init__にはクラスがあります。たとえばmodule1Class()module2Class()それぞれ。module2にはfile.py、 というクラスが含まれていmyFileClass()ます。

私がやりたいことは、/foo/bar/__init__.py次のように Django プロジェクトにインポートできるように、いくつかのコードを入れることです。

from foo.bar.module1 import module1Class
from foo.bar.module2 import module2Class
from foo.bar.module2.file import myFileClass

モジュールを持つディレクトリのリストは、次のような Django 構成のタプルに含まれています。

module_list = ("/modules", "/other_modules",)

私は次のような変数を使用__import__vars()て動的に生成しようとしました:

import os
import sys 

for m in module_list:
    sys.path.insert(0, m)
    for d in os.listdir(m):
        if os.path.isdir(d):
            vars()[d] = getattr(__import__(m.split("/")[-1], fromlist=[d], d)

しかし、それはうまくいかないようです。これを行う方法はありますか?

ありがとう!

4

2 に答える 2

1

あなたのコードには少なくとも 1 つの問題があります。この線...

if os.path.isdir(d):

...相対パス名を返すため、動作しませんos.listdir()。したがって、それらを絶対パス名に変換する必要があります。そうしないと、例外を発生させるのではなく、パスが存在しないため (現在の作業ディレクトリに対して)が返されます。 (これはもっと理にかなっています、IMO)。os.path.isdir()False

次のコードは私のために働く...

import sys
import os

# Directories to search for packages
root_path_list = ("/modules", "/other_modules",)

# Make a backup of sys.path
old_sys_path = sys.path[:]

# Add all paths to sys.path first, in case one package imports from another
for root_path in root_path_list:
    sys.path.insert(0, root_path)

# Add new packages to current scope
for root_path in root_path_list:
    filenames = os.listdir(root_path)
    for filename in filenames:
        full_path = os.path.join(root_path, filename)
        if os.path.isdir(full_path):
            locals()[filename] = __import__(filename)

# Restore sys.path
sys.path[:] = old_sys_path

# Clean up locals
del sys, os, root_path_list, old_sys_path, root_path, filenames, filename, full_path

アップデート

考えてみると、そのようなファイルを含まないサブディレクトリがある場合に を__init__.py使用するよりも、 の存在を確認する方が安全かもしれません。そうしないと、は失敗します。os.path.isdir()__import__()

だから、あなたは行を変更することができます...

        full_path = os.path.join(root_path, filename)
        if os.path.isdir(full_path):
            locals()[filename] = __import__(filename)

...に...

        full_path = os.path.join(root_path, filename, '__init__.py')
        if os.path.exists(full_path):
            locals()[filename] = __import__(filename)

……でも、もったいないかも。

于 2013-06-26T14:38:24.833 に答える
0

私たちは弾丸をかみ砕き、物事のやり方を変えました。モジュールを見つけるためのディレクトリのリストが Django config に渡され、それぞれが sys.path に追加されます (Aya が言及したコメントと私が以前に行ったが、あまり満足していなかったことに似ています)。次に、その中の各モジュールについて をチェックし、__init__.py存在する場合は、その部分を使用せずにアプリ内で使用するモジュールとして処理しようとしますfoo.bar

これには、モジュールとの対話方法と、開発者がモジュールをコーディングする方法を調整する必要がありました (以前使用していたフル パス インポートの代わりに、モジュール内で相対インポートを使用する必要があります)。長期使用。

これらを INSTALLED_APPS に追加しなかったのは、依存関係の問題や不適切なコードが原因でモジュールをインポートできない場合に、そのモジュールがなくてもソフトウェアが実行し続ける例外処理を行うためです。それらが INSTALLED_APPS にある場合、それらの例外をいつどのように処理するかについて、その柔軟性を活用することはできません。

助けてくれてありがとう!

于 2013-07-05T01:45:34.673 に答える