Help with changes in traceback stack from Python 2.7 to Python 3.x
Andrew Konstantaras
akonsta at icloud.com
Sun Apr 27 14:56:39 EDT 2014
Thanks for the response and I can certainly see that this old code can be improved, but I respectfully disagree on the utility of this function. The flexibility of passing any number of arguments to the function and returning a dictionary is much easier than writing out dict(x=x, y=y, ...n=n). I also believe that "makeDict" makes my code very readable.
My question is around finding the names of the variables passed to a function from within the function. I have spent many hours looking on the web looking for where in the frames and stacks this information is stored. Does anyone have any insight where/how I can find the variables associated with the arguments in
dctA = makeDict(strA, intA)
from within the function
def makeDict(*args):
.... #need to find the variable names "strA" and "intA" in this context
---Andrew
On Apr 26, 2014, at 05:10 AM, Ned Batchelder <ned at nedbatchelder.com> wrote:
> On 4/26/14 1:50 AM, Andrew Konstantaras wrote:
> > I wrote the following code that works in Python 2.7 that takes the
> > variables passed to the function into a dictionary. The following call:
> >
> > strA = 'a'
> > intA = 1
> > dctA = makeDict(strA, intA)
> >
> > produces the following dictionary:
> >
> > {'strA':'a', 'intA':1}
> >
> > To access the names passed into the function, I had to find the
> > information by parsing through the stack. The code that used to work is:
> >
> > from traceback import extract_stack
> >
> > def makeDict(*args):
> > strAllStack = str(extract_stack())
> > intNumLevels = len(extract_stack())
> > intLevel = 0
> > blnFinished = False
> > while not blnFinished:
> > strStack = str(extract_stack()[intLevel])
> > if strStack.find("makeDict(") >0:
> > blnFinished = True
> > intLevel += 1
> > if intLevel >= intNumLevels:
> > blnFinished = True
> > strStartText = "= makeDict("
> > intLen = len(strStartText)
> > intOpenParenLoc = strStack.find(strStartText)
> > intCloseParenLoc = strStack.find(")", intOpenParenLoc)
> > strArgs = strStack[ intOpenParenLoc+intLen : intCloseParenLoc ].strip()
> > lstVarNames = strArgs.split(",")
> > lstVarNames = [ s.strip() for s in lstVarNames ]
> > if len(lstVarNames) == len(args):
> > tplArgs = map(None, lstVarNames, args)
> > newDict = dict(tplArgs)
> > return newDict
> > else:
> > return "Error, argument name-value mismatch in function 'makeDict'.
> > lstVarNames: " + str(lstVarNames) + "\n args: " + str(args), strAllStack
> >
> > The same code does not work in Python 3.3.4. I have tried parsing
> > through the stack information and frames and I can't find any reference
> > to the names of the arguments passed to the function. I have tried
> > inspecting the function and other functions in the standard modules, but
> > I can't seem to find anything that will provide this information.
>
> 1) This is a very strange function. Instead of going to all this
> trouble, why not use:
>
> dctA = dict(strA=strA, intA=intA)
>
> Yes, you have to repeat the names, but you'd be done by now, it works on
> both versions of Python, and people reading your code would understand
> what it does.
>
> 2) Why is your code examining the entire stack? The frame you want is
> the one just above you. Why are you stringifying the tuple produced by
> extract_stack when the source line you want is the fourth element? Why
> are you using a while loop and a counter to iterate over elements of a list?
>
> 3) In the error case you return a tuple when the caller is expecting a
> dict? Why not raise an exception?
>
> 4) Your code only works if makeDict is assigned to a name. When I first
> tried it, I used "print(makeDict(...))", and it failed completely.
>
> 5) You haven't mentioned what goes wrong on Python 3, but when I tried
> it, I got:
>
> Traceback (most recent call last):
> File "foo3.py", line 34, in <module >
> d = makeDict(a, b)
> File "foo3.py", line 27, in makeDict
> newDict = dict(list(tplArgs))
> TypeError: 'NoneType' object is not callable
>
> Looking at your code, I see:
>
> tplArgs = map(None, lstVarNames, args)
>
> I didn't realize map accepted a callable of None (TIL!), but it no
> longer does in Python 3. You'll have to do this a different way.
>
> But seriously: just use dict() and be done with it. There's a lot here
> that can be much simpler if you learn to use Python as it was meant to
> be used. You are swimming upstream, there are easier ways.
>
> >
> > Can anyone point me in the direction to find this information? Any help
> > is appreciated.
> >
> > ---Andrew
> >
> >
> >
>
>
> --
> Ned Batchelder, http://nedbatchelder.com
>
> --
> https://mail.python.org/mailman/listinfo/python-list
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20140427/811bd63a/attachment.html>
More information about the Python-list
mailing list