deepcopy raises TypeError for method/function?

  • Thread starter OKB (not okblacke)
  • Start date
O

OKB (not okblacke)

I've noticed some peculiar behavior from copy.deepcopy: if you pass
it a method or function object, it raises a TypeError somewhere in
copy_reg saying "function() takes at least 2 arguments (0 given)". I'm
guessing this is the constructor for functions, and it's somehow being
incorrectly called, but I'm not really sure.

This behavior is annoying, however. I realize the deepcopy
documentation warns that it doesn't handle copying certain things, but
its behavior when asked to copy those things varies. For instance,
deepcopy(SomeClass) just silently returns the same SomeClass object. I
would expect deepcopy(someObj.someMethod) to do likewise, just returning
the same method object.

Does anyone have any pointers on this? It seems that certain types
are safe to deepcopy (even if they're not actually copied) whereas
others are not. Do I just have to manually typecheck for functions and
methods? Are there any other types that might raise such an error?

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
A

Alex Martelli

OKB (not okblacke) said:
deepcopy(SomeClass) just silently returns the same SomeClass object. I
would expect deepcopy(someObj.someMethod) to do likewise, just returning
the same method object.

Does anyone have any pointers on this? It seems that certain types
are safe to deepcopy (even if they're not actually copied) whereas
others are not. Do I just have to manually typecheck for functions and
methods? Are there any other types that might raise such an error?

You can use copy_reg to register an identity function as the way to
'copy' function and methods, if that floats your boat. And sure, there
are other types that raise errors, imagine copying a file object, a
socket, ...!


Alex
 
O

OKB (not okblacke)

Alex said:
You can use copy_reg to register an identity function as the way to
'copy' function and methods, if that floats your boat. And sure,
there are other types that raise errors, imagine copying a file
object, a socket, ...!

Wasn't someone just saying on another thread, though, that copy
doesn't "officially" use copy_reg?

Anyway, I guess my real question is, is there any safe way to do
something like

for a in someList:
b = copy.deepcopy(a)

. . . without having to know ahead of time what kinds of objects
are in someList? I could maybe use try/except to catch failure, but if
deepcopy fails like it did with methods, will it always throw a
TypeError, or might it raise some other kind of error? Alternatively,
is there a way to tell without actually attempting the deepcopy whether
it will be able to copy the object or not?

--
--OKB (not okblacke)
Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is
no path, and leave a trail."
--author unknown
 
A

Alex Martelli

OKB (not okblacke) said:
Wasn't someone just saying on another thread, though, that copy
doesn't "officially" use copy_reg?

Right, it was me -- I was carping about the inconsistency between [a]
claiming that if something ain't in the docs it don't count, telling
people to look in the sources as the ultimate reference. We're doing
both things, holding both contradictory stances at once, and I don't
like that:-(. This one bug in the docs we'll fix, of course, but the
overall strategy remains a problem.
Anyway, I guess my real question is, is there any safe way to do
something like

for a in someList:
b = copy.deepcopy(a)

. . . without having to know ahead of time what kinds of objects
are in someList? I could maybe use try/except to catch failure, but if

Failure is surely possible, since not all types are copyable. Yes, you
can use a try/except -- but if you enter the except clause the copy
won't have happened, so if you need it you're in trouble.
deepcopy fails like it did with methods, will it always throw a
TypeError, or might it raise some other kind of error? Alternatively,

TypeError would be normal, but I don't think it can be guaranteed.
Consider...:

In [1]: class X(object):
...: def __init__(self): self.xxx = 44
...: def __getstate__(self): return self.xx # oops
...:

Here, a copy.deepcopy(X()) will end with AttributeError, because of the
oops... for different kind of oopses you could surely have all kinds of
errors. 'except Exception:" thus seems sounder.
is there a way to tell without actually attempting the deepcopy whether
it will be able to copy the object or not?

None I can think of, sorry.


Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top