Максимальная глубина рекурсии превышена py2App

Я довольно тщательно искал Google, но не могу найти ответ на этот вопрос. Когда я пытаюсь собрать с помощью py2app, я получаю эту ошибку: возможно ли, что это вызвано использованием в коде модуля, такого как «gspread»? Или потому что я использую wxpython? Беспокоит то, что «python setup.py py2app -A» работает без проблем.

running py2app
creating /Users/Bailejor/Desktop/build/bdist.macosx-10.5-x86_64/python2.7-standalone/app
creating /Users/Bailejor/Desktop/build/bdist.macosx-10.5-x86_64/python2.7-standalone/app/collect
creating /Users/Bailejor/Desktop/build/bdist.macosx-10.5-x86_64/python2.7-standalone/app/temp
creating build/bdist.macosx-10.5-x86_64/python2.7-standalone/app/lib-dynload
creating build/bdist.macosx-10.5-x86_64/python2.7-standalone/app/Frameworks
*** using recipe: virtualenv ***
*** using recipe: ftplib ***
*** using recipe: lxml ***
*** using recipe: PIL ***
*** using recipe: xml ***
*** using recipe: sip ***
*** using recipe: matplotlib ***
*** using recipe: pydoc ***
*** using recipe: docutils ***
*** using recipe: scipy ***
Traceback (most recent call last):
  File "setup.py", line 18, in <module>
    setup_requires=['py2app'],
  File "//anaconda/lib/python2.7/distutils/core.py", line 151, in setup
    dist.run_commands()
  File "//anaconda/lib/python2.7/distutils/dist.py", line 953, in run_commands
    self.run_command(cmd)
  File "//anaconda/lib/python2.7/distutils/dist.py", line 972, in run_command
    cmd_obj.run()
  File "//anaconda/lib/python2.7/site-packages/py2app-0.9-py2.7.egg/py2app/build_app.py", line 659, in run
    self._run()
  File "//anaconda/lib/python2.7/site-packages/py2app-0.9-py2.7.egg/py2app/build_app.py", line 865, in _run
    self.run_normal()
  File "//anaconda/lib/python2.7/site-packages/py2app-0.9-py2.7.egg/py2app/build_app.py", line 943, in run_normal
    self.process_recipes(mf, filters, flatpackages, loader_files)
  File "//anaconda/lib/python2.7/site-packages/py2app-0.9-py2.7.egg/py2app/build_app.py", line 833, in process_recipes
    find_needed_modules(mf, packages=rval['packages'])
  File "//anaconda/lib/python2.7/site-packages/modulegraph/find_modules.py", line 289, in find_needed_modules
    m = mf.import_hook(package, None, ["*"])
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 927, in import_hook
    for s in self._ensure_fromlist(m, fromlist):
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 1053, in _ensure_fromlist
    submod = self._import_module(sub, fullname, m)
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 1260, in _scan_ast
    visitor.visit(co)
  File "//anaconda/lib/python2.7/ast.py", line 241, in visit
    return visitor(node)
  File "//anaconda/lib/python2.7/ast.py", line 249, in generic_visit
    self.visit(item)
  File "//anaconda/lib/python2.7/ast.py", line 241, in visit
    return visitor(node)
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 615, in visit_ImportFrom
    self._process_import(node.module or '', _ast_names(node.names), level)
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 1029, in _load_tail
    result = self._import_module(head, mname, result)
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 1105, in _import_module
    m = self._load_module(fqname, fp, pathname, stuff)
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 1178, in _load_module
    self._scan_code(co, m)
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 1251, in _scan_code
    self._scan_ast(co, m)
  File "//anaconda/lib/python2.7/site-packages/modulegraph/modulegraph.py", line 1260, in _scan_ast
    visitor.visit(co)
  File "//anaconda/lib/python2.7/ast.py", line 241, in visit
    return visitor(node)
  File "//anaconda/lib/python2.7/ast.py", line 249, in generic_visit
    self.visit(item)
  File "//anaconda/lib/python2.7/ast.py", line 241, in visit
    return visitor(node)
  File "//anaconda/lib/python2.7/ast.py", line 251, in generic_visit
    self.visit(value)
  File "//anaconda/lib/python2.7/ast.py", line 241, in visit
    return visitor(node)
  File "//anaconda/lib/python2.7/ast.py", line 245, in generic_visit
    for field, value in iter_fields(node):
RuntimeError: maximum recursion depth exceeded

Вот мой код, как было предложено (спасибо за предложение):

import wx
import wx.grid as gridlib
import numpy as np
import pandas as pd
import csv
import matplotlib.pyplot as plt
import os
import itertools
from itertools import chain
import getpass
import gspread
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.figure import Figure
import sys

####################################################################################################
class TopPanel(wx.Panel):
    """"""
    #Top PANEL
    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent=parent)

        grid = gridlib.Grid(self)
        grid.CreateGrid(25,12)
        grid.SetColLabelValue(0, "Index")
        self.buttonPlus = wx.Button(self, wx.NewId(), "+", size=(50, 28))
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(grid, 0, wx.EXPAND)
        self.SetSizer(sizer)


########################################################################################################
class BottomPanel(wx.Panel):
    """"""
    #Bottom PANEL
    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent=parent)
        #Sizers------------------------------------------------------------
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer2=wx.BoxSizer(wx.VERTICAL)
        self.sizer3=wx.BoxSizer(wx.VERTICAL)
        self.sizer4=wx.BoxSizer(wx.VERTICAL)
        #-----------------------------------------------------------------
        self.figure = Figure(figsize=(1,2))
        self.axe = self.figure.add_subplot(111)
        self.figurecanvas = FigureCanvas(self, -1, self.figure)
        self.barseries = wx.TextCtrl(self, size=(140, -1))
        self.lblname = wx.StaticText(self, label="Enter Series to Bar:")
        self.buttonUpdate = wx.Button(self, label="Update Figure")
        self.buttonPlot = wx.Button(self, wx.NewId(), "Plot", size=(60,28))
        self.buttonClear = wx.Button(self, wx.NewId(), "Clear", size=(60,28))
        self.buttonSave=wx.Button(self, wx.NewId(), "Save", size=(60, 28))
        self.buttonNext=wx.Button(self, wx.NewId(), "Next", size=(60, 28))
        self.buttonPrev=wx.Button(self, wx.NewId(), "Last", size=(60, 28))
        self.buttonGplot=wx.Button(self, wx.NewId(), "Gplot", size=(60, 28))
        sampleList = ['Yes', 'No']
        self.rb = wx.RadioBox(self, wx.ID_ANY, "Secondary Vertical Axis", wx.DefaultPosition, wx.DefaultSize, sampleList, 2, wx.RA_SPECIFY_COLS)
        #Button Binders------------------------------------------------------
        self.buttonSave.Bind(wx.EVT_BUTTON, self.saveFig)
        self.buttonPlot.Bind(wx.EVT_BUTTON, self.plotFig)
        self.buttonClear.Bind(wx.EVT_BUTTON, self.clearFig)
        self.buttonGplot.Bind(wx.EVT_BUTTON, self.googlefunc)
        self.buttonNext.Bind(wx.EVT_BUTTON, self.nextButtonFunc)
        self.buttonPrev.Bind(wx.EVT_BUTTON, self.prevButtonFunc)
        #--------------------------------------------------------------------
        #Add to Sizers-------------------------------------------------------
        self.sizer.Add(self.figurecanvas, proportion=2, border=1, flag=wx.ALL | wx.EXPAND)
        self.sizer2.Add(self.rb, proportion=0, border=2, flag=wx.ALL)
        self.sizer2.Add(self.lblname, proportion=0, border=2, flag=wx.ALL)
        self.sizer2.Add(self.barseries, proportion=0, border=2, flag=wx.ALL)
        self.sizer2.Add(self.buttonUpdate, proportion=0, border=2, flag=wx.ALL)

        self.sizer3.Add(self.buttonGplot, proportion=0, border=2, flag=wx.ALL)
        self.sizer3.Add(self.buttonPrev, proportion=0, border=2, flag=wx.ALL)
        self.sizer3.Add(self.buttonPlot, proportion=0, border=2, flag=wx.ALL)
        self.sizer4.Add(self.buttonSave, proportion=0, border=2, flag=wx.ALL)
        self.sizer4.Add(self.buttonNext, proportion=0, border=2, flag=wx.ALL)
        self.sizer4.Add(self.buttonClear, proportion=0, border=2, flag=wx.ALL)

        self.sizer.Add(self.sizer2, 0, wx.TOP)
        self.sizer.Add(self.sizer3, 0)
        self.sizer.Add(self.sizer4, 0)
        self.SetSizer(self.sizer)
        self.sheetcounter=[]

#Begin Google Sheets Function-------------------------------------------------------------
    def googlefunc(self, e):
        usernam = wx.TextEntryDialog(None, "Enter Novel Responses Username")
        if usernam.ShowModal()==wx.ID_OK:
            usernm=usernam.GetValue()
            usernam.Destroy()
        else:
            usernam.Destroy()
        convert=usernm + "@gmail.com"

        dlg1 = wx.PasswordEntryDialog(parent=None,message="Please enter your password")
        if dlg1.ShowModal()==wx.ID_OK:
            pw=dlg1.GetValue()
            dlg1.Destroy

        gc = gspread.login(convert, pw)
        dlg2 = wx.TextEntryDialog(None, "Which client would you like to view progress of?")
        if dlg2.ShowModal()==wx.ID_OK:
            self.client=dlg2.GetValue()
            dlg2.Destroy()

        wks = gc.open(self.client)

        for i, worksheet in enumerate(wks.worksheets()):
            filename = self.client + '-worksheet' + str(i) + '.csv'
            with open(filename, 'wb') as f:
                writer = csv.writer(f)
                writer.writerows(worksheet.get_all_values())
            self.sheetcount = i + 1
        print "There are "+str(self.sheetcount)+" client goals that have been charted."
        self.gplot(jor=0, currentsheet=0)

    def gplot(self, jor, currentsheet):
        lst = ["Bar Series", "Multiple Vertical Axes"]
        if  jor < (self.sheetcount):
            df = pd.read_csv((self.client+'-worksheet'+str(currentsheet)+'.csv'), index_col=0, header=0, sep=',')
            phasechange = df['Phase Change'].dropna()
            phaselabel=df['Phase Label'].values
            phaselabel1=phaselabel
            print phaselabel1
            get_title=str(df['Title'].iloc[0])
            get_y=str(df['Y-Axis Title'].iloc[0])
            get_x=df.index.name
            df=df.dropna(axis=1)
            markers=itertools.cycle(('o', 's', 'D', 's', 'h', '8'))
            markercolor=itertools.cycle(('k', 'w'))
            max_value=(df.values.max()) * 1.5
            print max_value
            fig=plt.figure(1)
            ax=self.axe
            ax.spines['top'].set_visible(False)
            ax.spines['right'].set_visible(False)
            ax.yaxis.set_ticks_position('left')
            ax.xaxis.set_ticks_position('bottom')
            ax.set_ylabel(get_y)
            ax.axes.set_ylim([0, max_value])
            fig.set_tight_layout(True)
            for col in (df):
                df[col].plot(x=get_x, grid=False, marker=markers.next(), markerfacecolor=markercolor.next(), title=get_title, color='k', ax=ax)
                for phase in phasechange:
                    ax.axvline(x=phase, ymin=0, ymax=1.0, linewidth=12, color='w')
                    ax.axvline(x=phase, ymin=0, ymax=1.0, linewidth=1, color='k')
            phasechange = phasechange + 1
            self.figurecanvas.draw()




        #dlg3 = wx.MultiChoiceDialog( self, "Choose Specific Options for your plot", "Plot Options", lst)
        #if (dlg3.ShowModal() == wx.ID_OK):
            #selections = dlg3.GetSelections()
            #strings = [lst[x] for x in selections]
            #if "Bar Series" and "Multiple Vertical Axes" in strings:
                #print "You selected Bar series and multi vert axis"
                #dlg4 = wx.TextEntryDialog(None, "Which series would you like to bar?")
                #if dlg4.ShowModal()==wx.ID_OK:
                    #get_bar=dlg2.GetValue()
                    #dlg4.Destroy()
                #use Recursion here call gplot again"
                #dlg3.Destroy()
            #elif "Bar Series" in strings:
            #print "You selected Bar Series"
        #else:
            #dlg3.Destroy()

        return (jor, currentsheet)

                #self.deletecsv(sheetcount, currentsheet, client)

    #def deletecsv(self, sheetcount, currentsheet, client):
    #currentsheet=0
    #for _ in xrange(sheetcount):
    #os.remove(client+'-worksheet'+str(currentsheet)+'.csv')
    #currentsheet=currentsheet + 1
#--END Gplot Function-------------------------------------------------------------------------


#--Next Button Function-----------------------------------------------------------------------
    def nextButtonFunc(self, event):
        if len(self.sheetcounter) < (self.sheetcount):
            self.sheetcounter.append('l')
            i2=len(self.sheetcounter)
            jor, currentsheet = self.gplot(jor=i2, currentsheet=i2)
            self.axe.clear()
            print jor, currentsheet
            self.gplot(jor, currentsheet)

#--Prev Button Function-----------------------------------------------------------------------
    def prevButtonFunc(self, event):
        if 0< len(self.sheetcounter) <= (self.sheetcount):
            del self.sheetcounter[-1]
            i2=len(self.sheetcounter)
            jor, currentsheet = self.gplot(jor=i2, currentsheet=i2)
            self.axe.clear()
            print jor, currentsheet
            self.gplot(jor, currentsheet)
#--Save Figure Function--------------------------------------------------------------------
    def saveFig(self, event):
        filename=wx.TextEntryDialog(None, "Please enter a name to save figure", "Save")
        if filename.ShowModal()==wx.ID_OK:
            filename=filename.GetValue()
            self.figure.savefig(filename+".png")
#--Plot Figure Function--------------------------------------------------------------------
    def plotFig(self, event):

        self.axe.plot(range(10), color='green')
        self.figurecanvas.draw()
#--Clear Figure Function------------------------------------------------------------------
    def clearFig(self, event):
        del self.sheetcounter[:]
        self.figure.set_canvas(self.figurecanvas)
        self.axe.clear()
        self.figurecanvas.draw()
        self.SetSize((self.Size[0],self.figurecanvas.Size[1]))
        currentsheet=0
        for _ in xrange(self.sheetcount):
            os.remove(self.client+'-worksheet'+str(currentsheet)+'.csv')
            currentsheet=currentsheet +1
#########################################################################################################
class MyForm(wx.Frame):
    #MAIN FRAME
    #-------------------------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, title="SSD-Single Subject Designs", size=(1100, 650))

        splitter = wx.SplitterWindow(self)
        topP = TopPanel(splitter)
        bottomP = BottomPanel(splitter)
#----Start Menubar-----------------------------------------------------------------------
        menubar=wx.MenuBar()
        first=wx.Menu()
        second=wx.Menu()
        third=wx.Menu()
        fourth=wx.Menu()

        first.Append(wx.NewId(),"New Window", "This is a new window")
        first.Append(wx.NewId(),"Open...", "This will open a new window")
        first.Append(wx.NewId(), "Save Dataframe", "")
        first.Append(wx.NewId(), "Save As", "")
        first.AppendSeparator()
        quitter=first.Append(wx.NewId(),"Exit", "This will close the program")

        second.Append(wx.NewId(), "Cut", "This will cut the selection")
        second.Append(wx.NewId(), "Copy", "This will copy the selection")
        second.Append(wx.NewId(), "Paste", "This will paste the selection")

        mbl=wx.Menu()
        mbl.Append(wx.ID_ANY, "Two Baselines")
        mbl.Append(wx.ID_ANY, "Three Baselines")
        mbl.Append(wx.ID_ANY, "Four Baselines")
        mbl.Append(wx.ID_ANY, "Five Baselines")
        mbl.Append(wx.ID_ANY, "Six Baselines")

        third.Append(wx.NewId(), "Analyze IOA", "Analyze Interobserver Agreement Data")

        third.Append(wx.NewId(), "AB.. Design", "A simple baseline, intervention design with x phases.")
        third.AppendMenu(wx.ID_ANY, "Multiple Baseline Design", mbl)
        third.Append(wx.NewId(), "Changing Criterion Design", "A design with several subphases within the treatment phase.")
        third.Append(wx.NewId(), "Multiple-Treatment Design", "A design with 2 or more treatments in an intervention phase.")
        googler=fourth.Append(wx.NewId(), "Import from Google Sheets", "Import a data set from Google")
        fourth.Append(wx.NewId(), "Import from Excel", "Import a data set from Microsoft Excel")
        menubar.Append(first, "File")
        menubar.Append(second, "Edit")
        menubar.Append(third, "Analyze")
        menubar.Append(fourth, "Import")
        self.SetMenuBar(menubar)

        self.Bind(wx.EVT_MENU, self.Quit, quitter)
        #self.Bind(wx.EVT_MENU, self.googlefunc, googler)
#--ENDMENUBAR-----------------------------------------------------------------------------
        # split the window
        splitter.SplitHorizontally(topP, bottomP)
        splitter.SetMinimumPaneSize(200)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(splitter, 1, wx.EXPAND)
        self.SetSizer(sizer)
#--QUIT FUNCTION-------------------------------------------------------------------------
    def Quit(self, e):
        yesNoBox=wx.MessageDialog(None, "Are you sure you want to quit?", "Exit?", wx.YES_NO)
        yesNoAnswer=yesNoBox.ShowModal()
        print yesNoAnswer
        if yesNoAnswer == 5103:
            self.Close()
            yesNoBox.Destroy()
        else:
            yesNoBox.Destroy()
#End of Quit Function---------------------------------------------------------------------
########################################################################################################
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

person user2229838    schedule 04.02.2015    source источник
comment
Трассировка не должна начинаться с modulegraph, а должна указывать на строку в вашем модуле, верно? Возможно, вы пропустили вставку начальных строк из трассировки?   -  person Roberto    schedule 04.02.2015
comment
Извините, вы правы. Я думал, что это просто повторяется, поэтому я сократил его. Обновлено сейчас!   -  person user2229838    schedule 04.02.2015
comment
Пришлось еще немного укоротить. Было 300 тыс. символов с ограничением в 30 тыс., но я заснял хотя бы начало.   -  person user2229838    schedule 04.02.2015
comment
Итак, у меня нет ответа (извините), но я читал еще один вопрос и, по-видимому, у py2app могут быть проблемы с рекурсией для других модулей, таких как scipy, и их можно избежать, увеличив предел рекурсии с помощью ie sys.setrecursionlimit(1500) (по умолчанию 1000). Я не могу сказать, сработает ли это, но вы хотели бы попробовать?   -  person Roberto    schedule 04.02.2015
comment
Кроме того, возможно, вас заинтересует это? Я вижу, вы используете wx.   -  person Roberto    schedule 04.02.2015
comment
Спасибо за вашу помощь, я уже пробовал трюк с ограничением рекурсии, но безрезультатно. Я не уверен, как выполнить второе. Я вижу несколько файлов path.py на своем компьютере.   -  person user2229838    schedule 05.02.2015
comment
Модуль pandas также вызывает эту ошибку рекурсии. Удалите его и проверьте.   -  person sidpat    schedule 22.02.2016


Ответы (1)


Я также сталкиваюсь с этой проблемой, и я пробовал много способов и решений для ее решения. Наконец, я обнаружил, что проблема связана с модулем modulegraph. Затем я ищу https://pypi.python.org/pypi/py2app/ и в В конце этой страницы указано, что требуются дистрибутивы modulegraph (>=0,15) macholib (>=1,8) altgraph (>=0,13), поэтому все, что вам нужно сделать, это загрузить последний файл пакета modulegraph, macholib и altgraph, загрузите файл whl и используйте pip install XXX.whl. все модули должны быть самыми новыми. Надеюсь, это поможет вам.

person Damon Zheng    schedule 01.12.2017