diff --git a/product/ERP5/Document/BusinessTemplate.py b/product/ERP5/Document/BusinessTemplate.py
index e6f4db0507de70846c62ed77cb5071b190ccb815..f6496995323457539e589ec7a61236c27fa29650 100644
--- a/product/ERP5/Document/BusinessTemplate.py
+++ b/product/ERP5/Document/BusinessTemplate.py
@@ -577,7 +577,7 @@ class BaseTemplateItem(Implicit, Persistent):
   def importFile(self, bta, **kw):
     bta.importFiles(item=self)
 
-  def removeProperties(self, obj):
+  def removeProperties(self, obj, export):
     """
     Remove unneeded properties for export
     """
@@ -587,7 +587,8 @@ class BaseTemplateItem(Implicit, Persistent):
 
     attr_list = [ '_dav_writelocks', '_filepath', '_owner', 'uid',
                   'workflow_history', '__ac_local_roles__' ]
-    attr_list += {
+    if export:
+      attr_list += {
         'ERP5 Python Script': ('_lazy_compilation', 'Python_magic'),
       }.get(meta_type, ())
 
@@ -599,7 +600,13 @@ class BaseTemplateItem(Implicit, Persistent):
       if not obj.getProperty('business_template_include_content', 1):
         obj.deletePdfContent()
     elif meta_type == 'ERP5 Python Script':
-      obj._code = None
+      if export:
+        # XXX forward compatibility: set to None instead of deleting '_code'
+        #     so that old BT code can import recent BT
+        obj._code = None
+      else:
+        # save result of automatic compilation
+        obj._p_changed = 1
     elif  interfaces.IIdGenerator.providedBy(obj):
       for dict_name in ('last_max_id_dict', 'last_id_dict'):
         if getattr(obj, dict_name, None) is not None:
@@ -717,7 +724,7 @@ class ObjectTemplateItem(BaseTemplateItem):
       relative_url = '/'.join([url,id])
       obj = p.unrestrictedTraverse(relative_url)
       obj = obj._getCopy(context)
-      obj = self.removeProperties(obj)
+      obj = self.removeProperties(obj, 1)
       id_list = obj.objectIds() # FIXME duplicated variable name
       if hasattr(aq_base(obj), 'groups'): # XXX should check metatype instead
         # we must keep groups because they are deleted along with subobjects
@@ -744,7 +751,7 @@ class ObjectTemplateItem(BaseTemplateItem):
       except AttributeError:
         raise AttributeError, "Could not find object '%s' during business template processing." % relative_url
       _recursiveRemoveUid(obj)
-      obj = self.removeProperties(obj)
+      obj = self.removeProperties(obj, 1)
       id_list = obj.objectIds()
       if hasattr(aq_base(obj), 'groups'): # XXX should check metatype instead
         # we must keep groups because they are deleted along with subobjects
@@ -836,7 +843,7 @@ class ObjectTemplateItem(BaseTemplateItem):
       # FIXME: Why not use the importXML function directly? Are there any BT5s
       # with actual .zexp files on the wild?
       obj = connection.importFile(file_obj, customImporters=customImporters)
-    self.removeProperties(obj)
+    self.removeProperties(obj, 0)
     self._objects[file_name[:-4]] = obj
 
   def preinstall(self, context, installed_item, **kw):
@@ -847,7 +854,7 @@ class ObjectTemplateItem(BaseTemplateItem):
       for path in self._objects:
         if installed_item._objects.has_key(path):
           upgrade_list.append((path,
-            self.removeProperties(installed_item._objects[path])))
+            self.removeProperties(installed_item._objects[path], 0)))
         else: # new object
           modified_object_list[path] = 'New', type_name
       # update _p_jar property of objects cleaned by removeProperties
@@ -1038,10 +1045,6 @@ class ObjectTemplateItem(BaseTemplateItem):
 
           # install object
           obj = self._objects[path]
-          if getattr(obj, 'meta_type', None) in ('Script (Python)',
-                                                 'ERP5 Python Script'):
-            if getattr(obj, '_code') is None:
-              obj._compile()
           if getattr(aq_base(obj), 'groups', None) is not None:
             # we must keep original order groups
             # because they change when we add subobjects
@@ -1379,7 +1382,7 @@ class PathTemplateItem(ObjectTemplateItem):
         obj = obj.__of__(context)
         _recursiveRemoveUid(obj)
         id_list = obj.objectIds()
-        obj = self.removeProperties(obj)
+        obj = self.removeProperties(obj, 1)
         if hasattr(aq_base(obj), 'groups'):
           # we must keep groups because it's ereased when we delete subobjects
           groups = deepcopy(obj.groups)
@@ -1496,7 +1499,7 @@ class CategoryTemplateItem(ObjectTemplateItem):
       relative_url = '/'.join([url,id])
       obj = p.unrestrictedTraverse(relative_url)
       obj = obj._getCopy(context)
-      obj = self.removeProperties(obj)
+      obj = self.removeProperties(obj, 1)
       id_list = obj.objectIds()
       if id_list:
         self.build_sub_objects(context, id_list, relative_url)
@@ -1512,7 +1515,7 @@ class CategoryTemplateItem(ObjectTemplateItem):
       obj = p.unrestrictedTraverse(relative_url)
       obj = obj._getCopy(context)
       _recursiveRemoveUid(obj)
-      obj = self.removeProperties(obj)
+      obj = self.removeProperties(obj, 1)
       include_sub_categories = obj.__of__(context).getProperty('business_template_include_sub_categories', 0)
       id_list = obj.objectIds()
       if len(id_list) > 0 and include_sub_categories:
@@ -1828,10 +1831,6 @@ class WorkflowTemplateItem(ObjectTemplateItem):
             self._backupObject(action, trashbin, container_path, object_id, keep_subobjects=1)
             container.manage_delObjects([object_id])
           obj = self._objects[path]
-          if getattr(obj, 'meta_type', None) in ('Script (Python)',
-                                                 'ERP5 Python Script'):
-            if getattr(obj, '_code') is None:
-              obj._compile()
           obj = obj._getCopy(container)
           container._setObject(object_id, obj)
           obj = container._getOb(object_id)
@@ -2634,7 +2633,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
         obj=obj.aq_parent
         connection=obj._p_jar
       obj = connection.importFile(file, customImporters=customImporters)
-      self.removeProperties(obj)
+      self.removeProperties(obj, 0)
       self._objects[file_name[:-4]] = obj
     else:
       LOG('Business Template', 0, 'Skipping file "%s"' % (file_name, ))
@@ -2727,7 +2726,7 @@ class ActionTemplateItem(ObjectTemplateItem):
           continue
         raise NotFound('Action %r not found' % id)
       key = posixpath.join(url[-2], url[-1], value)
-      self._objects[key] = self.removeProperties(action)
+      self._objects[key] = self.removeProperties(action, 1)
       self._objects[key].wl_clearLocks()
 
   def install(self, context, trashbin, **kw):
@@ -5060,8 +5059,8 @@ Business Template is a set of definitions, such as skins, portal types and categ
         f1 = StringIO() # for XML export of New Object
         f2 = StringIO() # For XML export of Installed Object
         # Remove unneeded properties
-        new_object = new_item.removeProperties(new_object)
-        installed_object = installed_item.removeProperties(installed_object)
+        new_object = new_item.removeProperties(new_object, 1)
+        installed_object = installed_item.removeProperties(installed_object, 1)
         # XML Export in memory
         OFS.XMLExportImport.exportXML(new_object._p_jar, new_object._p_oid, f1)
         OFS.XMLExportImport.exportXML(installed_object._p_jar, 
diff --git a/product/ERP5Type/tests/ERP5TypeTestCase.py b/product/ERP5Type/tests/ERP5TypeTestCase.py
index 60bbf7c2775ac8e0b638374a66fe785d4a4f4020..af27175e37dccc73caea04e389be668a6d606add 100644
--- a/product/ERP5Type/tests/ERP5TypeTestCase.py
+++ b/product/ERP5Type/tests/ERP5TypeTestCase.py
@@ -1230,6 +1230,24 @@ class ZEOServerTestCase(ERP5TypeTestCase):
     self.zeo_server.close_server()
 
 
+class lazy_func_prop(object):
+  """Descriptor to delay the compilations of Python Scripts
+     until some of their attributes are accessed.
+  """
+  default_dict = {}
+  def __init__(self, name, default):
+    self.name = name
+    self.default_dict[name] = default
+  def __get__(self, instance, owner):
+    if self.name not in instance.__dict__:
+      instance.__dict__.update(self.default_dict)
+      instance._orig_compile()
+    return instance.__dict__[self.name]
+  def __set__(self, instance, value):
+    instance.__dict__[self.name] = value
+  def __delete__(self, instance):
+    del instance.__dict__[self.name]
+
 @onsetup
 def optimize():
   '''Significantly reduces portal creation time.'''
@@ -1241,26 +1259,44 @@ def optimize():
 
   # Delay the compilations of Python Scripts until they are really executed.
   from Products.PythonScripts.PythonScript import PythonScript
-  PythonScript_compile = PythonScript._compile
+  # In the future, Python Scripts will be exported without those 2 attributes:
+  PythonScript.func_code = lazy_func_prop('func_code', None)
+  PythonScript.func_defaults = lazy_func_prop('func_defaults', None)
+
+  PythonScript._orig_compile = PythonScript._compile
   def _compile(self):
-    self._lazy_compilation = 1
+    # mark the script as being not compiled
+    for name in lazy_func_prop.default_dict:
+      self.__dict__.pop(name, None)
   PythonScript._compile = _compile
   PythonScript_exec = PythonScript._exec
   def _exec(self, *args):
-    if getattr(self, '_lazy_compilation', 0):
-      self._lazy_compilation = 0
-      PythonScript_compile(self)
+    self.func_code # trigger compilation if needed
     return PythonScript_exec(self, *args)
   PythonScript._exec = _exec
   from Acquisition import aq_parent
   def _makeFunction(self, dummy=0): # CMFCore.FSPythonScript uses dummy arg.
     self.ZCacheable_invalidate()
-    PythonScript_compile(self)
+    self.__dict__.update(lazy_func_prop.default_dict)
+    self._orig_compile()
     if not (aq_parent(self) is None or hasattr(self, '_filepath')):
       # It needs a _filepath, and has an acquisition wrapper.
       self._filepath = self.get_filepath()
   PythonScript._makeFunction = _makeFunction
 
+  # XXX Previous implementation of this 'optimize' function requires that
+  #     Python Scripts always contain up-to-date data for 'func_code' and
+  #     'func_defaults' properties, so make sure we always export them.
+  #     This compatibility code is not required for normal ERP5 instances
+  #     because scripts are compiled at BT installation.
+  from Products.ERP5Type.Document.BusinessTemplate import BaseTemplateItem
+  BaseTemplateItem_removeProperties = BaseTemplateItem.removeProperties
+  def removeProperties(self, obj, export):
+    if export and isinstance(obj, PythonScript):
+      obj.func_code # trigger compilation if needed
+    return BaseTemplateItem_removeProperties(self, obj, export)
+  BaseTemplateItem.removeProperties = removeProperties
+
   # Do not reindex portal types sub objects by default
   # We will probably disable reindexing for other types later
   full_indexing_set = set(os.environ.get('enable_full_indexing', '').split(','))