5

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?

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
stej
  • 28,745
  • 11
  • 71
  • 104
  • Can you replicate this problem using just python, an not iron python. – Preet Sangha Feb 28 '10 at 21:26
  • I don't know how to import .NET assemblies to python (I thought it is not possible). So, I can not replicate that with my current knowledge. – stej Feb 28 '10 at 21:33
  • Probably not what you want to hear, but you could define your models in C# and import them into your IronPython environment. I'll be keen to know how you end up resolving this, if at all. – tarn Feb 28 '10 at 21:42
  • I hope there is pure IronPython solution :) – stej Feb 28 '10 at 22:01

2 Answers2

2

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
  • 12,978
  • 7
  • 43
  • 70
  • 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 Mar 08 '10 at 05:42
-1

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
  • 6,478
  • 20
  • 25
  • 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 Mar 01 '10 at 07:36
  • Agree. I want to use features of object databases, which would not be possible. – stej Mar 01 '10 at 21:02