Dvc: RecursionError from Repo('.').graph()[0].reverse()

Created on 12 Jul 2019  路  4Comments  路  Source: iterative/dvc

Please provide information about your setup
DVC version(i.e. dvc --version), Platform and method of installation (pip, homebrew, pkg Mac, exe (Windows), DEB(Linux), RPM(Linux))

dvc --version
> 0.51.1

Installed via pip, on Ubuntu 16.04.6 LTS.

The code:

from dvc.repo import Repo
Repo('.').graph()[0].reverse()

fails with the following error:

---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
<ipython-input-7-90086e6e0e64> in <module>
----> 1 r.graph()[0].reverse()

~/miniconda3/envs/py36_v11/lib/python3.6/site-packages/networkx/classes/digraph.py in reverse(self, copy)
   1195             H = self.__class__()
   1196             H.graph.update(deepcopy(self.graph))
-> 1197             H.add_nodes_from((n, deepcopy(d)) for n, d in self.node.items())
   1198             H.add_edges_from((v, u, deepcopy(d)) for u, v, d
   1199                              in self.edges(data=True))

~/miniconda3/envs/py36_v11/lib/python3.6/site-packages/networkx/classes/digraph.py in add_nodes_from(self, nodes_for_adding, **attr)
    470 
    471         """
--> 472         for n in nodes_for_adding:
    473             # keep all this inside try/except because
    474             # CPython throws TypeError on n not in self._succ,

~/miniconda3/envs/py36_v11/lib/python3.6/site-packages/networkx/classes/digraph.py in <genexpr>(.0)
   1195             H = self.__class__()
   1196             H.graph.update(deepcopy(self.graph))
-> 1197             H.add_nodes_from((n, deepcopy(d)) for n, d in self.node.items())
   1198             H.add_edges_from((v, u, deepcopy(d)) for u, v, d
   1199                              in self.edges(data=True))

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy)
    238     memo[id(x)] = y
    239     for key, value in x.items():
--> 240         y[deepcopy(key, memo)] = deepcopy(value, memo)
    241     return y
    242 d[dict] = _deepcopy_dict

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    278     if state is not None:
    279         if deep:
--> 280             state = deepcopy(state, memo)
    281         if hasattr(y, '__setstate__'):
    282             y.__setstate__(state)

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy)
    238     memo[id(x)] = y
    239     for key, value in x.items():
--> 240         y[deepcopy(key, memo)] = deepcopy(value, memo)
    241     return y
    242 d[dict] = _deepcopy_dict

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    278     if state is not None:
    279         if deep:
--> 280             state = deepcopy(state, memo)
    281         if hasattr(y, '__setstate__'):
    282             y.__setstate__(state)

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy)
    238     memo[id(x)] = y
    239     for key, value in x.items():
--> 240         y[deepcopy(key, memo)] = deepcopy(value, memo)
    241     return y
    242 d[dict] = _deepcopy_dict

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    278     if state is not None:
    279         if deep:
--> 280             state = deepcopy(state, memo)
    281         if hasattr(y, '__setstate__'):
    282             y.__setstate__(state)

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy)
    238     memo[id(x)] = y
    239     for key, value in x.items():
--> 240         y[deepcopy(key, memo)] = deepcopy(value, memo)
    241     return y
    242 d[dict] = _deepcopy_dict

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    278     if state is not None:
    279         if deep:
--> 280             state = deepcopy(state, memo)
    281         if hasattr(y, '__setstate__'):
    282             y.__setstate__(state)

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    148     copier = _deepcopy_dispatch.get(cls)
    149     if copier:
--> 150         y = copier(x, memo)
    151     else:
    152         try:

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _deepcopy_dict(x, memo, deepcopy)
    238     memo[id(x)] = y
    239     for key, value in x.items():
--> 240         y[deepcopy(key, memo)] = deepcopy(value, memo)
    241     return y
    242 d[dict] = _deepcopy_dict

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in deepcopy(x, memo, _nil)
    178                     y = x
    179                 else:
--> 180                     y = _reconstruct(x, memo, *rv)
    181 
    182     # If is its own copy, don't memoize.

~/miniconda3/envs/py36_v11/lib/python3.6/copy.py in _reconstruct(x, memo, func, args, state, listiter, dictiter, deepcopy)
    279         if deep:
    280             state = deepcopy(state, memo)
--> 281         if hasattr(y, '__setstate__'):
    282             y.__setstate__(state)
    283         else:

~/miniconda3/envs/py36_v11/lib/python3.6/site-packages/dvc/path_info.py in __getattr__(self, name)
    185 
    186     def __getattr__(self, name):
--> 187         return getattr(self.parsed, name)
    188 
    189     @cached_property

... last 1 frames repeated, from the frame below ...

~/miniconda3/envs/py36_v11/lib/python3.6/site-packages/dvc/path_info.py in __getattr__(self, name)
    185 
    186     def __getattr__(self, name):
--> 187         return getattr(self.parsed, name)
    188 
    189     @cached_property

RecursionError: maximum recursion depth exceeded
bug

All 4 comments

Hi @PeterFogh !

Thanks for reporting it! That part of the python API is not officially released yet, so there definitely will be some bugs 馃檨 Are you using it in one of your scripts? Could you describe the scenario? E.g. how big is the graph and what networkx version are you using?

You are welcome. Yaah. I know, I'm pushing DVC to the experimental level 馃槣.
Your scenario is to save the DVC pipeline graph as a PNG image file - which we store in MLflow as an artefact.

The pipeline looks like this by dvc pipeline show --ascii:

+-------------------+                        +---------------------+           +------------------------------+           +---------------------------+
| sql_extration.dvc |                        | dawiki_download.dvc |           | landbrugsinfo_extraction.dvc | **********| lkontoplan_extraction.dvc |
+-------------------+                        +---------------------+***        +------------------------------+*      ****+---------------------------+
          *                                                            ******************** *                 ********               *
          *                                       *********************      ******         *         ********                      *
          *                  *********************                                 ***     *      ****                             *
  +---------------+**********                                                 +-----------------------+                           *
  | splitting.dvc |*******                                                    | pretrain_word2vec.dvc |                           *
  +---------------+       ***************                                     +-----------------------+                           *
          *                              ****************                                 *                                       *
          *                                              ***************                  *                                       *
          *                                                             ********          *                                       *
          *                                                                    +--------------------+                             *
          *                                                             *******| train_word2vec.dvc |                             *
          *                                              ***************       +--------------------+                             *
          *                                **************                                 *                                       *
          *                 ***************                                               *                                       *
          *         ********                                                              *                                       *
+-------------------+                               +--------------+                    ***                                       *
| featurization.dvc |***                        ****| training.dvc |**              ****                                          *
+-------------------+   *********       ********    +--------------+  ******   *****                                              *
          *                     *********                    *            ********                                                *
          *             ********         *********            *       ****        ******                                          *
          *        *****                          *****       *    ***                  ******                                    *
  +----------------+                              +-----------------------+                   ****                            *****
  | prediction.dvc |******                        | model_to_azure_sa.dvc |                  ***                     *********
  +----------------+      ***********             +-----------------------+                **               *********
                                     ***********                                        ***        *********
                                                ***********                          ***  *********
                                                           ***********             *******
                                                                      ****+---------+
                                                                          | Dvcfile |
                                                                          +---------+

networkx version is:

conda list -n py36_v11 | grep networkx
> networkx                  2.3                        py_0

@PeterFogh if you don't need to do anything with the Repo object after that, or if you can initialize it again, try to run reverse(copy=False).

I wonder if it's networkx bug? Or something it's something related to us due to deepcopy calls.

k, was able to reproduce it this way:

from dvc.path_info import URLInfo
u = URLInfo("ssh://[email protected]:/test1/test2/test3")
copy.deepcopy(u)

so, it something related to our UrlInfo implementation.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mdscruggs picture mdscruggs  路  3Comments

shcheklein picture shcheklein  路  3Comments

mfrata picture mfrata  路  3Comments

dmpetrov picture dmpetrov  路  3Comments

TezRomacH picture TezRomacH  路  3Comments