Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #4133 > unrolled thread
| Started by | "ivdneut@gmail.com" <ivdneut@gmail.com> |
|---|---|
| First post | 2011-04-27 06:56 -0700 |
| Last post | 2011-04-29 01:36 -0700 |
| Articles | 5 — 3 participants |
Back to article view | Back to comp.lang.python
unpickling derived LogRecord in python 2.7 from python2.6 "ivdneut@gmail.com" <ivdneut@gmail.com> - 2011-04-27 06:56 -0700
Re: unpickling derived LogRecord in python 2.7 from python2.6 Peter Otten <__peter__@web.de> - 2011-04-27 18:41 +0200
Re: unpickling derived LogRecord in python 2.7 from python2.6 Vinay Sajip <vinay_sajip@yahoo.co.uk> - 2011-04-27 13:39 -0700
Re: unpickling derived LogRecord in python 2.7 from python2.6 Peter Otten <__peter__@web.de> - 2011-04-28 09:22 +0200
Re: unpickling derived LogRecord in python 2.7 from python2.6 "ivdneut@gmail.com" <ivdneut@gmail.com> - 2011-04-29 01:36 -0700
| From | "ivdneut@gmail.com" <ivdneut@gmail.com> |
|---|---|
| Date | 2011-04-27 06:56 -0700 |
| Subject | unpickling derived LogRecord in python 2.7 from python2.6 |
| Message-ID | <dddb61de-6964-41c4-9f14-d9d1d5fdb2b7@cu4g2000vbb.googlegroups.com> |
Hello all,
I have a service that runs in python 2.6.4. This service sends
LogRecords to a log monitoring app on my workstation running python
2.7. The LogRecord class is derived:
class LogRecord(logging.LogRecord):
def __init__(self, name, level, fn, lno, user, hostname, msg,
args, exc_info, func=None):
if sys.version_info[1] > 4:
logging.LogRecord.__init__(self, name, level, fn, lno,
msg, args, exc_info, func)
else:
logging.LogRecord.__init__(self, name, level, fn, lno,
msg, args, exc_info)
Now when I try to unpickle it:
record = cPickle.loads(data)
I get a TypeError exception:
TypeError: ('__init__() takes at least 8 arguments (1 given)', <class
'...gRecord'>, ())
I've searched the web and this group, but most results are old. It
worked when my workstation still ran python 2.6.
Thank you,
Ian.
[toc] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2011-04-27 18:41 +0200 |
| Message-ID | <ip9gtg$s9p$1@solani.org> |
| In reply to | #4133 |
ivdneut@gmail.com wrote:
> I have a service that runs in python 2.6.4. This service sends
> LogRecords to a log monitoring app on my workstation running python
> 2.7. The LogRecord class is derived:
>
> class LogRecord(logging.LogRecord):
>
> def __init__(self, name, level, fn, lno, user, hostname, msg,
> args, exc_info, func=None):
>
> if sys.version_info[1] > 4:
> logging.LogRecord.__init__(self, name, level, fn, lno,
> msg, args, exc_info, func)
> else:
> logging.LogRecord.__init__(self, name, level, fn, lno,
> msg, args, exc_info)
>
> Now when I try to unpickle it:
>
> record = cPickle.loads(data)
>
> I get a TypeError exception:
>
> TypeError: ('__init__() takes at least 8 arguments (1 given)', <class
> '...gRecord'>, ())
>
> I've searched the web and this group, but most results are old. It
> worked when my workstation still ran python 2.6.
The Problem is that as of Python 2.7 logging.LogRecord has become a newstyle
class which is pickled/unpickled differently. I don't know if there is an
official way to do the conversion, but here's what I've hacked up.
The script can read pickles written with 2.6 in 2.7, but not the other way
round.
$ cat pickle_logrec.py
import sys
import pickle
import logging
class LogRecord(logging.LogRecord):
def __init__(self, name, level, fn, lno, user, hostname, msg, args,
exc_info, func=None):
if sys.version_info[1] > 4:
logging.LogRecord.__init__(self, name, level, fn, lno, msg,
args, exc_info, func)
else:
logging.LogRecord.__init__(self, name, level, fn, lno, msg,
args, exc_info)
def makeLogRecord():
return LogRecord(*[None]*9)
if issubclass(LogRecord, object):
print "LogRecord is a newstyle class"
class MyUnpickler(pickle.Unpickler):
def find_class(self, *args):
klass = pickle.Unpickler.find_class(self, *args)
if klass is LogRecord:
return makeLogRecord
return klass
else:
print "LogRecord is an oldstyle class"
MyUnpickler = pickle.Unpickler
if __name__ == "__main__":
if "--load" in sys.argv:
print "loading"
with open("tmp.pickle") as f:
restored = MyUnpickler(f).load()
print restored
else:
print "dumping"
with open("tmp.pickle", "w") as f:
f.write(pickle.dumps(LogRecord("yadda", *[None]*8)))
$ python2.6 pickle_logrec.py
LogRecord is an oldstyle class
dumping
$ python2.6 pickle_logrec.py --load
LogRecord is an oldstyle class
loading
<LogRecord: yadda, None, None, None, "None">
$ python2.7 pickle_logrec.py --load
LogRecord is a newstyle class
loading
<LogRecord: yadda, None, None, None, "None">
No warranty, use at your own risk.
[toc] | [prev] | [next] | [standalone]
| From | Vinay Sajip <vinay_sajip@yahoo.co.uk> |
|---|---|
| Date | 2011-04-27 13:39 -0700 |
| Message-ID | <bb7009bd-e93d-470e-9077-9fa12046dd7f@q20g2000vbx.googlegroups.com> |
| In reply to | #4140 |
On Apr 27, 5:41 pm, Peter Otten <__pete...@web.de> wrote: > The Problem is that as of Python 2.7logging.LogRecord has become a newstyle > class which is pickled/unpickled differently. I don't know if there is an > official way to do the conversion, but here's what I've hacked up. > The script can read pickles written with 2.6 in 2.7, but not the other way > round. > [code snipped] I don't know about "official", but another way of doing this is to pickle just the LogRecord's __dict__ and send that over the wire. The logging package contains a function makeLogRecord(d) where d is a dict. This is the approach used by the examples in the library documentation which pickle events for sending across a network: http://docs.python.org/howto/logging-cookbook.html#sending-and-receiving-logging-events-across-a-network The built-in SocketHandler pickles the LogRecord's __dict__ rather than the LogRecord itself, precisely because of the improved interoperability over pickling the instance directly. Regards, Vinay Sajip
[toc] | [prev] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2011-04-28 09:22 +0200 |
| Message-ID | <ipb4hd$9rf$1@solani.org> |
| In reply to | #4162 |
Vinay Sajip wrote:
> On Apr 27, 5:41 pm, Peter Otten <__pete...@web.de> wrote:
>
>> The Problem is that as of Python 2.7logging.LogRecord has become a
>> newstyle class which is pickled/unpickled differently. I don't know if
>> there is an official way to do the conversion, but here's what I've
>> hacked up. The script can read pickles written with 2.6 in 2.7, but not
>> the other way round.
>> [code snipped]
>
> I don't know about "official", but another way of doing this is to
> pickle just the LogRecord's __dict__ and send that over the wire. The
> logging package contains a function makeLogRecord(d) where d is a
> dict.
You are right, my approach is too complicated and only needed when the OP
cannot modify the sending script -- which is unlikely.
> This is the approach used by the examples in the library documentation
> which pickle events for sending across a network:
>
> http://docs.python.org/howto/logging-cookbook.html#sending-and-receiving-
logging-events-across-a-network
>
> The built-in SocketHandler pickles the LogRecord's __dict__ rather
> than the LogRecord itself, precisely because of the improved
> interoperability over pickling the instance directly.
As a minimal change ensuring that the logging.LogRecord subclass used by the
OP is a newstyle class in 2.6 with
class LogRecord(logging.LogRecord, object):
#...
should work, too.
[toc] | [prev] | [next] | [standalone]
| From | "ivdneut@gmail.com" <ivdneut@gmail.com> |
|---|---|
| Date | 2011-04-29 01:36 -0700 |
| Message-ID | <632d00c3-3dc8-4a10-8ce8-579b5cfcb2e7@j31g2000yqe.googlegroups.com> |
| In reply to | #4211 |
On Apr 28, 9:22 am, Peter Otten <__pete...@web.de> wrote: > Vinay Sajip wrote: > > On Apr 27, 5:41 pm, Peter Otten <__pete...@web.de> wrote: > > >> The Problem is that as of Python 2.7logging.LogRecord has become a > >> newstyle class which is pickled/unpickled differently. I don't know if > >> there is an official way to do the conversion, but here's what I've > >> hacked up. The script can read pickles written with 2.6 in 2.7, but not > >> the other way round. > >> [code snipped] > > > I don't know about "official", but another way of doing this is to > > pickle just the LogRecord's __dict__ and send that over the wire. The > > logging package contains a function makeLogRecord(d) where d is a > > dict. > > You are right, my approach is too complicated and only needed when the OP > cannot modify the sending script -- which is unlikely. > > > This is the approach used by the examples in the library documentation > > which pickle events for sending across a network: > > >http://docs.python.org/howto/logging-cookbook.html#sending-and-receiv... > > logging-events-across-a-network > > > > > The built-in SocketHandler pickles the LogRecord's __dict__ rather > > than the LogRecord itself, precisely because of the improved > > interoperability over pickling the instance directly. > > As a minimal change ensuring that the logging.LogRecord subclass used by the > OP is a newstyle class in 2.6 with > > class LogRecord(logging.LogRecord, object): > #... > > should work, too. I tried this, but it didn't work. Pickling the __dict__ and then use makeLogRecord does the trick. Thank you very much for the excellent help, Ian.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web