Voici une page qui m’a bien servi :

http://fadace.developpez.com/oracle/nls/

Il suffit de mettre la bonne variable d’environnement. Dans les shell qui lancent mon zope (bin/runzope et bin/zopectl) , voici ce que j’ai ajouté pour régler le problème :

# Mon système et mon zope sont configurés en UTF-8. Je laisse american parce que la base est en American.

NLS_LANG=AMERICAN_AMERICA.AL32UTF8

export  NLS_LANG

Zope and threads

June 1st, 2008

Même Ruby connaît des problèmes et ne donne pas accès aux threads dans ROR.

Ce code est inspiré de : http://www.zopelabs.com/cookbook/1058719806

# -*- coding: utf-8 -*-
__doc__ = “”
Contient la classe ZopeThread qui permet de manipuler des objets en Zope dans un Thread lancé séparément et de contourner l’exception
ConnectionStateError: Shouldn’t load state for 0×031ae3 when the connection is closed.

La méthode principale qu’il vous procure est getContext() qui vous renvoi le context de l’objet Application de zope (racine de Zope).

A partir de là, vous pouvez acquérir les objets.

Voir un exemple d’utilisation dans le module AnnuaireEntreprises/Gestionnaires/GestionnaireExport/Export.py

En dérivant votre thread de ZopeThread, vous pourrez garder une connexion ouverte à la ZODB et manipuler les objets qu’elle contient.

Copié de la recette de runyaga trouvée dans le zope cookbook à cette adresse : http://www.zopelabs.com/cookbook/1058719806

“”

# Imports Zope
from ZPublisher.HTTPRequest import HTTPRequest
from ZPublisher.HTTPResponse import HTTPResponse
from ZPublisher.BaseRequest import RequestContainer

from threading import Thread

class ZopeThread(Thread):
    “”
    “
“”
    def getContext(self):
        “”
        “
“”
        # This import statement must go here. If not, DB == None.
        from Zope2 import DB
        self.conn = DB.open()
        root = self.conn.root()
        app = root[‘Application’]
        resp = HTTPResponse(stdout=None)
        env = {
        ‘SERVER_NAME’:‘localhost’,
        ‘SERVER_PORT’:‘8080′,
        ‘REQUEST_METHOD’:‘GET’
        }
        req = HTTPRequest(None, env, resp)
        return app.__of__(RequestContainer(REQUEST = req))

    def closeConnexion(self):
        “”
        “
“”
        self.conn.close()

Exemple d’utilisation :

class DoItInBackGround(ZopeThread):
    “”
    A class that does things in background so that long processing do not affect user experience.
    For example, you can use this to do a database extraction (to csv or excel file) requested by a user,
    after completing a filtering form. The extraction is processed here in a separate thread, and when it finishes,
    the user is sent the URL to the exported file instead of the user waiting for the server to respond after
    he finishes this long processing.
    “
“”
    def run(self):
        “”
        “
“”
        # getContext is intherited from Zopthread
        ctx = self.getContext()
        cnx = self.connectToDB()
        results = self.extractDatabase(cnx)
        self.writeToCSVFile(results,“/var/www/zope/data/DBExtract.csv”)
        URL = self.getURLOfFile(“/var/www/zope/data/DBExtract.csv”)
        # Now using the context and acquisition to call ZODB obejcts.
        # Remember, ctx is root
        ctx.MailHost.sendmail(arguments go in here)
        # closeConnexion is intherited from Zopthread
        self.closeConnexion()

One way to do it is through external methods, because there is no restriction in imported modules. You can use any module you want, for instance, the logging module, which comes very handy when you need to log timestamped entries and sort them by level of importance (Debug, Info, Error, Critical and so on…)