0

私たちが遭遇するあらゆる種類の医療画像フォーマットの汎用リーダーを作成しようとしています。私はプロから学ぼうと思い、 PIL が一般的にファイルを読み取る方法を模倣しました(「Python Imaging Library」、フォーマット)。

私が理解しているように、PILには、可能な受け入れ関数のリストをループするオープン関数があります。機能すると、関連するファクトリ関数を使用して適切なオブジェクトをインスタンス化します。

だから私はこれをやろうとしました、そして私の(簡素化された)努力はここにあります:


pluginID = []     # list of all registered plugin IDs
OPEN = {}         # plugins have open and (maybe) accept functions as a tuple

_initialized = False

import os, sys

def moduleinit():
    '''Explicitly initializes the library.  This function 
    loads all available file format drivers.

    This routine has been lifted from PIL, the Python Image Library'''

    global _initialized
    global pluginID
    if _initialized:
        return 

    visited = {}

    directories = sys.path

    try:
        directories = directories + [os.path.dirname(__file__)]
    except NameError:
        pass

    # only check directories (including current, if present in the path)
    for directory in filter(isDirectory, directories):
        fullpath = os.path.abspath(directory)
        if visited.has_key(fullpath):
            continue
        for file in os.listdir(directory):
            if file[-19:] == "TestReaderPlugin.py":
                f, e = os.path.splitext(file)
                try:
                    sys.path.insert(0, directory)
                    try: # FIXME: this will not reload and hence pluginID 
                        # will be unpopulated leading to "cannot identify format"
                        __import__(f, globals(), locals(), [])
                    finally:
                        del sys.path[0]
                except ImportError:
                    print f, ":", sys.exc_value
        visited[fullpath] = None

    if OPEN:
        _initialized = True
        return 1

class Reader:
    '''Base class for image file format handlers.'''
    def __init__(self, fp=None, filename=None):

        self.filename = filename

        if isStringType(filename):
            import __builtin__
            self.fp = __builtin__.open(filename) # attempt opening

        # this may fail if not implemented
        self._open() # unimplemented in base class but provided by plugins

    def _open(self):
        raise NotImplementedError(
            "StubImageFile subclass must implement _open"
            )


# this is the generic open that tries to find the appropriate handler
def open(fp):
    '''Probe an image file

    Supposed to attempt all opening methods that are available. Each 
    of them is supposed to fail quickly if the filetype is invalid for its 
    respective format'''

    filename=fp

    moduleinit() # make sure we have access to all the plugins

    for i in pluginID:
        try:
            factory, accept = OPEN[i]
            if accept:
                fp = accept(fp)
                # accept is expected to either return None (if unsuccessful) 
                # or hand back a file handle to be used for opening                                 
                if fp:
                    fp.seek(0)  
                    return factory(fp, filename=filename) 
        except (SyntaxError, IndexError, TypeError): 
                pass # I suppose that factory is allowed to have these 
                # exceptions for problems that weren't caught with accept()
                # hence, they are simply ignored and we try the other plugins

    raise IOError("cannot identify format")

# --------------------------------------------------------------------
# Plugin registry

def register_open(id, factory, accept=None):
    pluginID.append(id)
    OPEN[id] = factory, accept

# --------------------------------------------------------------------
# Internal:

# type stuff
from types import  StringType

def isStringType(t):
    return isinstance(t, StringType)

def isDirectory(f):
    '''Checks if an object is a string, and that it points to a directory'''
    return isStringType(f) and os.path.isdir(f)

舞台裏で重要なのは、初めてファイルを開こうとしたときにすべての形式のプラグインを登録することです (moduleinit)。適格なすべてのプラグインは、アクセス可能なパスにあり、*TestReaderPlugin.py という名前が付けられている必要があります。(動的に)インポートされます。各プラグイン モジュールは、register_open を呼び出して ID、ファイルを作成するメソッド、および候補ファイルをテストするための受け入れ関数を提供する必要があります。

プラグインの例は次のようになります。


import TestReader

def _accept(filename):
    fp=open(filename,"r")
    # we made it here, so let's just accept this format
    return fp

class exampleTestReader(TestReader.Reader):
    format='example'

    def _open(self):
        self.data = self.fp.read()

TestReader.register_open('example', exampleTestReader, accept=_accept)

TestReader.open() は、ユーザーが使用する関数です。

import TestReader
a=TestReader.open(filename) # easy

それで - 問題はどこですか?まず、私はまだpythonicの方法を探しています。これでしょうか?私がそれを疑う理由は、moduleinit ステージの魔法が乱雑に見えるからです。PIL から直接コピーされます。主な問題: (TestReader) をリロードすると、ID が [] に初期化されるため、すべてが機能しなくなりますが、プラグインはリロードされません。


1. すべての形式に対して単純な open(filename) 呼び出しを許可し、
2. 適切にカプセル化されたプラグインのみを必要な形式に提供する必要がある汎用リーダーを設定するより良い方法はありますか?
3. リロードで動作しますか?

4

1 に答える 1

0

いくつかのガイドライン:

  1. バッファに「ピーク」の概念を使用して、理解できるデータ データがあるかどうかをテストします。
  2. インポーターの名前を知ることは、ユーザーが知りたくないことです (100 個のインポーターがあるとしたらどうなるでしょうか)。「ファサード」インターフェースを使用しますmedicimage.open(filepath)
  3. リロードに取り組むには、少しのロジックを実装する必要があります。
于 2011-03-30T17:54:30.367 に答える