Skip to content

Recursion bug in deepcopy #47293

Closed
Closed

Description

@Zeroth
mannequin
BPO 3043
Nosy @facundobatista, @avassalotti

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = <Date 2008-06-21.14:52:28.315>
created_at = <Date 2008-06-05.21:03:49.899>
labels = ['type-bug', 'library']
title = 'Recursion bug in deepcopy'
updated_at = <Date 2008-06-21.14:52:28.309>
user = 'https://bugs.python.org/Zeroth'

bugs.python.org fields:

activity = <Date 2008-06-21.14:52:28.309>
actor = 'facundobatista'
assignee = 'none'
closed = True
closed_date = <Date 2008-06-21.14:52:28.315>
closer = 'facundobatista'
components = ['Library (Lib)']
creation = <Date 2008-06-05.21:03:49.899>
creator = 'Zeroth'
dependencies = []
files = []
hgrepos = []
issue_num = 3043
keywords = []
message_count = 6.0
messages = ['67728', '67730', '67731', '67732', '67742', '68497']
nosy_count = 4.0
nosy_names = ['facundobatista', 'alexandre.vassalotti', 'gpolo', 'Zeroth']
pr_nums = []
priority = 'normal'
resolution = 'wont fix'
stage = None
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue3043'
versions = ['Python 2.5']

Activity

  1. Zeroth commented on Jun 5, 2008

    Zerothmannequin
    MannequinAuthor

    With the following code:
    class Vertex:
    def __init__(self, type):
    self.type = type
    self.color=-1
    self.edges=[]

    class Edge:
    	def __init__(self, V1, V2):
    		self.vertexes=[V1, V2]
    		V1.edges.append(self)
    		V2.edges.append(self)

    Where the references are cyclic(this is for a research project into
    graph algorithms), and using deepcopy, even on a tiny graph of five
    vertexes and 25 edges causes deepcopy to run into the recursion limit.
    At the very least, it should warn it can't copy the indicated object, as
    the references are cyclic. At the very most, it should be able to handle
    complex cyclic references like this properly.

  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    type-bugAn unexpected behavior, bug, or error
    on Jun 5, 2008
  3. Zeroth commented on Jun 5, 2008

    Zerothmannequin
    MannequinAuthor

    Whoops, sorry, correction, when there are 100 vertexes and 500 edges.

  4. gpolo commented on Jun 5, 2008

    gpolomannequin
    Mannequin

    This should have been fixed at 2.2, as long as you change your classes
    to new-style classes. If it still happens, post a sample code using your
    new code that uses new-style classes.

  5. Zeroth commented on Jun 5, 2008

    Zerothmannequin
    MannequinAuthor

    Same problem, even with new-style classes. Here, I'll show the function
    I use to generate the graph as well.

    class Vertex(object):
    	def __init__(self, type):
    		self.type = type
    		self.color=-1
    		self.edges=[]
    		
    
    		
    class Edge(object):
    	def __init__(self, V1, V2):
    		self.vertexes=[V1, V2]
    		V1.edges.append(self)
    		V2.edges.append(self)
    
    def generate(graph={'V':[], 'E':[]}, seed=777, vertexes=5, edges=25):
    	#generates a graph similar to the KEGG pathway database format.
    	# Purpose is for testing algorithms on a smaller scale "predicatible" graph
    	# For that reason, the "random" selections are seeded with a known
    number. This is to be able
    	# to measure efficacy, in that on the same graph, if algorithm A
    performs in half the time, its 
    	# not a characteristic of the graph, but the algorithm.
    	r=random.Random(seed)
    	p=[0, 0, 0, 0]
    	c=0
    	#generate vertices, with a regularly incremented set of numbers, to
    appear like the KEGG pathway database does.
    	while c!=vertexes:
    		#This is ugly, could be done easier in a loop. Fix later.
    		p[3]+=1
    		if p[3]>9:
    			p[3]=0
    			p[2]+=1
    		if p[2]>9:
    			p[2]=0
    			p[1]+=1
    		if p[1]>9:
    			p[1]=0
    			p[0]+=1
    		#we copy the set of numbers, due to the way python passes lists by
    reference, instead of by copy.
    		v=Vertex(p[:])
    		graph['V'].append(v)
    		c+=1
    	
    	
    	v=graph['V']
    	if len(v)!=vertexes:
    		print "Not enough vertices, aborting."
    		return graph
    	c=0
    	#randomly choose two vertices. Could even, randomly, be the same vertex.
    	# Then, connect an edge between them. Just creating the edge by
    implication,
    	# with the vertices passed, connects them all together.
    	while c!=edges:
    		v1=r.choice(v)
    		v2=r.choice(v)
    		graph['E'].append(Edge(v1, v2))
    		c+=1
    	
    	if len(graph['E']) !=edges:
    		print "Not enough edges, aborting."
    	return graph

    And here is how I use it:

    >>import graph, copy
    >>g=graph.generate(vertexes=100, edges=500)
    >>g2=copy.deepcopy(g)

    Thanks for the prompt response, this isn't critical in nature, just
    playing around with the graph, and wanted to alter a copy of it. Ran
    into this bug, thought I should report it. :)

    -Zeroth

  6. avassalotti commented on Jun 5, 2008

    @avassalotti
    Member

    Your graph is simply too deep for Python to handle it. The copy module
    (and also the pickle) pushes a new stack frame every time a new
    container object is encountered. Therefore, there is a recursion limit
    to prevent the interpreter from crashing.

    If you want, you can carefully increase the limit by using the function
    sys.setrecursionlimit. Using your example:

    >>> sys.setrecursionlimit(2000)
    >>> g2 = copy.deepcopy(g)
    >>> # no error

  7. facundobatista commented on Jun 21, 2008

    @facundobatista
    Member
  8. transferred this issue fromon Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions