0

A little background-- I have a Python program that makes plots from CSV files. I'm trying to make it more flexible by allowing a user to input between 1 and 3 files. I import the csv data into pandas data frames that are then used to generate a number of different plots.

I'm sure there's a better way to do what I'm doing, but I came across something strange (to me, at least) in my initial attempt to figure out if a user had input less than the maximum number of files.

Here is how I import the data:

# Imports the data.  The first two rows must be skipped due to the file format
data1 = pd.read_csv(filename1, skiprows=1, header=True)
if filename2 != '':
    data2 = pd.read_csv(filename2, skiprows=1, header=True)
if filename3 != '':
    data3 = pd.read_csv(filename3, skiprows=1, header=True)

So data2 and data3 are only defined if a user has provided a file name from my GUI. Later, I just wanted to use the existence of data2 and data3 to determine whether or not to plot the 2nd and 3rd data sets, respectively:

    try:
        axarr[1, 0].psd(data1[Ynew], NFFT=n_samples, Fs=fs, noverlap=n_overlap, window=mlab.window_hanning, label=baseFileName1)
    except KeyError:
        axarr[1, 0].psd(data1[Yold], NFFT=n_samples, Fs=fs, noverlap=n_overlap, window=mlab.window_hanning, label=baseFileName1)
    try:
        axarr[1, 0].psd(data2[Ynew], NFFT=n_samples, Fs=fs, noverlap=n_overlap, window=mlab.window_hanning, label=baseFileName2)
    except (UnboundLocalError, NameError):
        pass
    except KeyError:
        axarr[1, 0].psd(data2[Yold], NFFT=n_samples, Fs=fs, noverlap=n_overlap, window=mlab.window_hanning, label=baseFileName2)
    try:
        axarr[1, 0].psd(data3[Ynew], NFFT=n_samples, Fs=fs, noverlap=n_overlap, window=mlab.window_hanning, label=baseFileName3)
    except (UnboundLocalError, NameError):
        pass
    except KeyError:
        axarr[1, 0].psd(data3[Yold], NFFT=n_samples, Fs=fs, noverlap=n_overlap, window=mlab.window_hanning, label=baseFileName3)

And here's where it got weird. When I run the thing, it throws an UnboundLocalError telling me that 'NameError' is referenced before assignment. So that except block that's supposed to catch the UnboundLocalError isn't passing like I would expect. If I try to catch just the UnboundLocalError, a NameError is thrown. If I try to catch just a NameError, an UnboundLocalError is thrown. Can somebody explain to me what's going on here?

EDIT- Here's the traceback:

Error Traceback

ARRRcade
  • 9
  • 2
  • 2
    Please include a complete stack trace. – DYZ Aug 04 '17 at 18:42
  • Is this Python 2 or Python 3? – jwodder Aug 04 '17 at 18:43
  • It would also be useful to try to boil this down to a self-contained example. For one thing, that makes it easier to focus on the actual problem. For another, it often reveals an underlying cause. I suspect it will this time, referencing `NameError` should not be throwing any exceptions. – Peter DeGlopper Aug 04 '17 at 18:44
  • @jwodder -- Python 2.7 – ARRRcade Aug 04 '17 at 18:52
  • @DYZ added the traceback screen capture. – ARRRcade Aug 04 '17 at 18:57
  • According to the stack trace, the error is on line 342 of some file that is not included in the question. How can we reason about it? – DYZ Aug 04 '17 at 19:01
  • @DYZ-- line 342 is included here, I just didn't know how to include the line numbers (sorry, first post). The error is occurring on the line with the first attempt to catch the (UnboundLocalError, NameError). – ARRRcade Aug 04 '17 at 19:07
  • Can you search your file for "NameError = " to see if you are accidentally shadowing the builtin NameError with an assignment? That's the error you will get if you assign a variable 'input = 42' AFTER a call to the builtin input() function (all inside your own function). [See this question](https://stackoverflow.com/questions/20873285/unboundlocalerror-local-variable-input-referenced-before-assignment) – robert_x44 Aug 04 '17 at 19:36
  • @robert_x44-- I just searched, and I'm definitely not doing that anywhere. That's what has me so confused about this one. – ARRRcade Aug 04 '17 at 19:39
  • can you post the entire four_psd_plots function that includes the above try/except blocks. – robert_x44 Aug 04 '17 at 19:44
  • 2
    Most likely, you've accidentally written `except UnboundLocalError, NameError` somewhere, without parentheses, creating a local variable named `NameError`. – user2357112 Sep 05 '17 at 18:41
  • In this case, catching only `NameError` would have been enough, because `UnboundLocalError` is a subclass of `NameError` (at least in Python 3). – Eduard Luca Dec 05 '19 at 13:54

1 Answers1

-1

I've revisited this multiple times and there seems to be bug report for this sort of problem floating around out there. Regardless, Exceptions are relatively expensive operations. You can use something like the following to circumvent your problem and cut down on cycles.

data1 = None
data2 = None
data3 = None
if filename1 != '':
    data1 = ...
if filename2 != '':
    data2 = ...
if filename3 != '':
    data3 = ...

if data1 is not None:
    if Ynew in data1:
        axarr[1,0].psd(data1[Ynew] ...
    elif Yold in data1:
        axarr[1,0].psd(data1[Yold] ...
if data2 is not None:
    if Ynew in data2:
        axarr[1,0].psd(data2[Ynew] ...
    elif Yold in data2:
        axarr[1,0].psd(data2[Yold] ...
if data3 is not None:
    if Ynew in data3:
        axarr[1,0].psd(data3[Ynew] ...
    elif Yold in data3:
        axarr[1,0].psd(data3[Yold] ...
anomeric
  • 688
  • 5
  • 17
  • catching the exception is probably less expensive than doing O(n) search over `dataN` all the time. – cowbert Dec 04 '18 at 03:47