22

OpenERP pythonコード開発サイクルは、コードを編集し、サーバーを再起動してテストすることです。サーバーを再起動する必要があります。これは、ソースコードをメモリに再ロードするためですが、作業ペースに煩わしい遅延が追加されます。

Pythonは非常に動的な言語なので、実行中のPythonインタープリター(アプリサーバー)にコードモジュールをオンザフライでリロードさせて、アプリサーバーを再起動せずにテストできるようにする方法があるのでしょうか。

更新:reload @ecatmurによって提案され たパスをたどると、以下のコードを取得しましたが、それでも機能しません:

class module(osv.osv):
    _inherit = "ir.module.module"

    def action_reload(self, cr, uid, ids, context=None):
        for obj in self.browse(cr, uid, ids, context=context):
            modulename = 'openerp.addons.' + obj.name
            tmp = __import__(modulename)
            pycfile = tmp.__file__
            modulepath = string.replace(pycfile, ".pyc", ".py")
            code=open(modulepath, 'rU').read()
            compile(code, modulename, "exec")
            execfile(modulepath)
            reload( sys.modules[modulename] )
        openerp.modules.registry.RegistryManager.delete(cr.dbname)
        openerp.modules.registry.RegistryManager.new(cr.dbname)
4

5 に答える 5

14

reload組み込み関数は、単一のモジュールをリロードします。更新されたパッケージを再帰的にリロードするためのさまざまなソリューションがあります。Pythonインタープリターで更新されたパッケージを再インポートする方法を参照してください。

問題の一部は、リロードされたモジュールから新しいクラスなどを参照するように既存のオブジェクトを調整する必要があることです。再インポートはこれをかなりうまく行います。IPythonインタラクティブコンソールでは、autoreload拡張機能を使用していますが、IPythonの外部で使用するようには設計されていません。

于 2012-09-26T08:12:35.057 に答える
9

更新:v8以降、Odooサーバーは--auto-reloadこれを実行するオプションを提供します。

すばらしい質問です。私はよく同じことを考えてきました。__init__.py投稿したコードの主な問題は、OpenERPモジュールのファイルのみをリロードし、個々のファイルすべてをリロードしないことだと思います。ecatmurがreimport推奨するモジュールがそれを処理します。また、すべてをリロードする前に、モジュールのレポートパーサーとモデルクラスの登録を解除する必要がありました。

module_reloadモジュールをLaunchpadに投稿しました。osv_memoryモデルクラス、ウィザード、およびレポートパーサーの変更に対して機能するようです。古いスタイルのウィザードでは機能せず、機能しない他のシナリオが存在する可能性があります。

モジュールをリロードする方法は次のとおりです。

def button_reload(self, cr, uid, ids, context=None):
    for module_record in self.browse(cr, uid, ids, context=context):
        #Remove any report parsers registered for this module.
        module_path = 'addons/' + module_record.name
        for service_name, service in Service._services.items():
            template = getattr(service, 'tmpl', '')
            if template.startswith(module_path):
                Service.remove(service_name)

        #Remove any model classes registered for this module
        MetaModel.module_to_models[module_record.name] = []                    

        #Reload all Python modules from the OpenERP module's directory.
        modulename = 'openerp.addons.' + module_record.name
        root = __import__(modulename)
        module = getattr(root.addons, module_record.name)

        reimport(module)
    RegistryManager.delete(cr.dbname)
    RegistryManager.new(cr.dbname)
    return {}
于 2012-10-04T19:28:12.597 に答える
1

ipythonにはdeepreloadモジュールがあり、ドキュメントはここにあります:http: //ipython.org/ipython-doc/stable/api/generated/IPython.lib.deepreload.html#module-IPython.lib.deepreload

ipythonREPLの外部でも使用できると思います。

于 2012-10-02T09:54:27.650 に答える
1

開発を行っているだけの場合は、リロードは問題ありませんが、デプロイメントを行っている場合は、そのようなトリックを避ける必要があります。これは、100%の時間は機能しないためです。変更が反映されない微妙な点が常にあります。たとえば、一部のコードがオブジェクトへの参照を使用するのではなくオブジェクトをコピーする場合、リロード後も同じままになります。逆に、参照が正しく前方に伝播しない場合is、オブジェクトの1つが「古い」リリースされていないモジュールからのものであるため、機能すると予想されるときに比較は失敗します。100%確実な唯一の起動方法は、すべてをリロードすることです。これは、基本的にサーバーの再起動です。

開発を行っているだけでも、不完全なリロードの副作用である誤ったバグに遭遇することがあります。クリーンな再起動を試みることが起こらない場合は、ファントムバグを追跡するために長い時間を費やすことができます。したがって、これを行うことになった場合は、それを念頭に置いてください。

于 2012-10-03T19:04:46.917 に答える
0

リロード組み込み関数は、モジュールまたはパッケージをリロードします。ただし、OpenERPのコンテキストでは、OpenERPアドオンをリロードするにはXMLファイルなどを処理する必要があるため、もう少し必要です。ただし、OpenERPでこれを使用するとよいことに同意します。

于 2012-09-26T09:27:18.853 に答える