0

どこから何かをインポートするかを決定するのに役立つPythonスクリプト/関数を作成しようとしています。この機能はPyQt4専用に必要ですが、Python標準ライブラリ用に拡張して使用できる可能性があります。

これを実現するには、モジュール、共有オブジェクト、クラス、および場合によっては特定の検索用語のより多くの「タイプ」を動的に検索する必要があります。

モジュール/クラスなどを渡したい。文字列として、動的にインポートしてから検索します。

関数のインターフェースは次のようになります。

search(object_to_search, search_term)

例:

search('datetime', 'today') -> 'datetime.datetime.today'

search('PyQt4', 'NonModal') -> 'PyQt4.QtCore.Qt.NonModal'

search('PyQt4', 'QIcon') -> 'PyQt4.QtGui.QIcon'

これは、すべてを検索するための「*」のようなワイルドカードもサポートできると思いますが、 sys.pathこれは現時点で私が懸念している範囲を超えています。

このタイプのスクリプトは、PyQt4で特に役立ちます。上記のような「列挙型のような」ものはたくさんあり、NonModalそれらをインポートまたは参照する場所を見つけるのは面倒な場合があります。

例をPythonに変換するのは通常簡単なので、PyQt4情報にはC++Qtドキュメントをかなり使用する傾向があります。C++Qtのドキュメントはより包括的です。また、適切なQtのサンプルコードを見つけるのもはるかに簡単です。ただし、これらの「列挙型のような」属性の一部のインポート場所は、ドキュメントを手動で検索したり推測したりしない限り、PyQt4で見つけるのは困難です。目標は、このプロセスを自動化し、スクリプトに探しているものの場所を教えてもらうことです。

でオブジェクトを再帰的に検索する、モジュールdir()を使用する、inspect共有オブジェクトのインポート/検出のハッキーバージョンなど、これを実装するいくつかの異なる方法を試しました。以下は私のさまざまな実装ですが、どれも実際には正しく機能しません。

この種のことも可能ですか?もしそうなら、これを行うための最良の方法は何ですか?また、組み込みのものや関数などを省略して検索するものの数を減らしてみましたが、これが必要であるとか、正しいとは思えません。

試みられた解決策:

def search_obj_inspect(obj, search_term):
    """Search given object for 'search_term' with 'inspect' module"""

    import inspect

    def searchable_type(obj):
        is_class = inspect.isclass(obj)
        root_type_or_obj = is_class and obj not in [object, type]
        abstract_class = is_class and inspect.isabstract(obj)
        method_or_func = inspect.ismethod(obj) or inspect.isfunction(obj)
        try:
            hidden_attribute = obj.__name__.startswith('__')
        except AttributeError:
            hidden_attribute = False

        searchable = True

        # Avoid infinite recursion when looking through 'object' and 'type' b/c
        # they are members of each other
        if True in [abstract_class, root_type_or_obj, hidden_attribute,
                    method_or_func, inspect.isbuiltin(obj)]:
            searchable = False

        return searchable


    # FIXME: Search obj itself for search term? obj.__name__ == search_term?
    for n, v in inspect.getmembers(obj,
                                   predicate=lambda x: searchable_type(x)):
        if search_term in n:
            try:
                return v.__name__
            except AttributeError:
                return str(v)

    return None


def search_obj_dir(obj, search_term):
    """Search given object and all it's python submodules for attr"""

    import re
    import types
    SEARCHABLE_TYPES = (types.ModuleType, types.ClassType, types.InstanceType,
                        types.DictProxyType)

    for item in dir(obj):
        if item.startswith('__'):
            continue

        if re.search(search_term, item):
            return obj.__dict__[item].__module__
        else:
            try:
                submod = obj.__dict__[item]
            except (KeyError, AttributeError):
                # Nothing left to recursively search
                continue

            if not isinstance(submod, SEARCHABLE_TYPES):
                continue

            #mod = search_obj_dir(submod, search_term)
            #if mod:
                #return '.'.join([mod, submod.__name__])

    return None


def search_so(module, attr):
    """Search given modules shared objects for attr"""

    import os
    import re

    try:
        path = module.__path__[0]
    except (AttributeError, IndexError):
        return False

    for root, dirs, files in os.walk(path):
        for filename in files:
            if filename.endswith('.so'):
                py_module_name = filename.split('.')[0]
                so_module = __import__(module.__name__, globals(), locals(),
                                        [py_module_name])

                if re.search(attr, py_module_name):
                    return ''.join([module.__name__, '.', py_module_name])
                try:
                    found = search_obj_dir(
                                    so_module.__dict__[py_module_name], attr)
                except KeyError:
                    # This isn't a top-level so, might be a subpackage
                    # FIXME: Could recursively search SO as well, but imports
                    #        might get weird
                    continue

                if found:
                    return found
4

1 に答える 1

0

pydocモジュールを調べるためのヒントを提供してくれた@JonClementsに感謝します。pkgutilモジュールとinspectモジュールを組み合わせて、私が望んでいたことをほぼ達成する方法を見つけました。

「トリック」は、パッケージ内のすべてのモジュール(PyQt4など)をpkgutil.iter_modulesで調べ、パッケージ以外のすべてのオブジェクトをで検索できるようにすることinspect.getmembersです。一般的な考え方は次のとおりです。

for pkg in given_pkg:
    for module_or_class in pkg:
        for attribute in module_or_class:

あなたはここで完全な解決策を見ることができます。

于 2013-02-14T22:25:34.663 に答える