views:

212

answers:

2

I'd like to use object database to persist some classes created in IronPython. The database is db4o for .NET 2.0 (downloaded today). The code looks like this:

import clr
clr.AddReferenceToFileAndPath(r"C:\dev\Db4objects\db4o-7.12-net20\bin\net-2.0\Db4objects.Db4o.dll")
from Db4objects.Db4o import *
db = Db4oFactory.OpenFile(r'G:\IronPython\test\db4o\database.db')

class Person(object):  
  def __init__(self, name, age):
    self.Name = name
    self.Age = age

  def __str__(self):
    return 'Person: ' + self.Name + ' ' + str(self.Age)

p1 = Person('testp', 34)
db.Store(p1)

I get exception at db.Store(p1)

Unexpected char '$'
ThrowUncheckedException at offset 4 in file:line:column <filename unknown>:0:0
FatalShutdown at offset 136 in file:line:column <filename unknown>:0:0
AsTopLevelCall at offset 112 in file:line:column <filename unknown>:0:0
AsTopLevelStore at offset 34 in file:line:column <filename unknown>:0:0
StoreInternal at offset 69 in file:line:column <filename unknown>:0:0
Store at offset 66 in file:line:column <filename unknown>:0:0
Store at offset 12 in file:line:column <filename unknown>:0:0
Store at offset 15 in file:line:column <filename unknown>:0:0
   v Microsoft.Scripting.Actions.Calls.MethodCandidate.Caller.CallWithInstance(Object[] args, Boolean& shouldOptimize)
   v IronPython.Runtime.Types.BuiltinFunction.BuiltinMethodCaller`2.Call1(CallSite site, CodeContext context, TFuncType
func, T0 arg0)
   v System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
   v Microsoft.Scripting.Interpreter.DynamicInstruction`4.Run(InterpretedFrame frame)
   v Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
   v Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1)
   v IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx)
   v IronPython.Compiler.PythonScriptCode.Run(Scope scope)
   v IronPython.Hosting.PythonCommandLine.<>c__DisplayClass1.<RunOneInteraction>b__0()
Exception: Unexpected char '$'
CLR Exception:
    Exception
:
Unexpected char '$'

I suspect that the problem is with IronPython and its type system, because the class Person is not standard .NET class. I tried to persist System.IO.FileInfo and it worked well. How can I store an object that is instance of a class in IronPython?

A: 

You could use pickle to persist the instances:

import cPickle db.Store(cPickle.dumps(p1))

and then use cPickle.loads(...) to bring the object back.

Dino Viehland
That's not a good idea. It's nearly useless to store serialized objects in db4o, because you loose nearly all features db4o offers, like queries, updates etc.
Gamlor
Agree. I want to use features of object databases, which would not be possible.
stej
+2  A: 

Hi

Db4o uses the CLR-reflection mechanisms to retrieve meta-information of the objects, in order to store it. This works fine for C#, VB.NET etc. Languages such as IronPython and IronRuby used an additional layer on top the CLR to allow all the wonderful dynamics features.

Now when db4o uses the CLR-reflection is sees add the additional stuff which is used to implement the dynamic features. In the attempt to store this information is fails. There not a simple an elegant solution available today =(

  1. As already stated in the comments, you could define you data-object in C# or VB.NET, so that you have plain old CLR objects. I think this is the quickest solution and should work.
  2. You could 'teach' db4o about the object-model of python by writing you own reflector. But that's certainly not easy.
  3. Db4o has a 'SelfReflector' which is intended for environments without reflection. There basically add manually the required meta-info for each object. However I cannot find any documentation on this.

Another possibility would be to use a ODBMS which is created specially for Python, like ZODB instead of db4o. But I'm not sure if ZOBR runs on IronPython.

Gamlor
Thank you for your answer, it helps me very much even when negative. I'll have a look at #2 and #3, just for fun (if I really needed it I would do it as in #1).
stej