1

Obviously I'm doing something stupid. But what?

I get:

File "<path>", line 71, in args
    filename = filename
NameError: name 'filename' is not defined

...on the next-to-last line below ("filename = filename"):

def parseLog(filename, explain=False, omitminor=False, omitexpected=False, 
omitgdocs=False, args=None):
    print(filename)
    if not args:
        class args:
            filename = filename
            explain = explain

Yet the 2nd line above ("print(filename)") works fine. So, why the error?

In case you're wondering why I'm doing this in the first place, it's because the function parseLog() can also be called by the command line, like so:

def parseLogCLI():
    ''' parse command line for arguments '''

    parser = argparse.ArgumentParser()
    parser.add_argument('filename')
    parser.add_argument('-explain', action="store_true", help='Explain what program has done')
    parser.add_argument('-omitminor', action="store_true", help='Omit minor errors ' + repr(minor_errors))
    parser.add_argument('-omitexpected', action="store_true", help='Omit machines expected to be often offline')
    parser.add_argument('-omitgdocs', action="store_true", help='Omit errors on Google Docs native files (not copyable) ' + repr(gdocs))
    args = parser.parse_args()

    parseLog(arg.filename, args=args)

...so I'm trying to construct an 'arg' class (as argparse does) to pass to my function. If there's a better way to do this, I'm interested.

nerdfever.com
  • 1,652
  • 1
  • 20
  • 41

2 Answers2

2

With class args: you are starting the definition of a class. In that context, the first occurrence of filename defines a class attribute, which you are trying to assign from its own value before it is fully defined.

First of all, I think you should investigate in more details the concepts of classes, scopes, and instances. This will help you understand why your function argument filename is hidden by the new definition inside the class scope.

Silmathoron
  • 1,781
  • 1
  • 15
  • 32
  • They can use a different name either for the function argument or the class attribute to fix this. However, I would rather find a way to refactor the code so you don't need to create classes at runtime. It's possible to do that in python, and there are valid use cases. But 99% of the time, this only adds complexity without significant benefit. https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python?rq=1 – Håken Lid Nov 10 '18 at 20:37
0

It seems to me like you have a scope issue, in that the inner class 'arg' doesn't have access to the scope of the outer class. One solution would be to use the 'global' keyword like so:

def parseLog(filename, explain=False, omitminor=False, omitexpected=False, 
omitgdocs=False, args=None):
    global fname, expl
    fname = filename
    expl = explain
    print(filename)
    if not args:
        class args:
            filename = fname
            explain = expl

You can read more about Python variable scopes here.

SahilMak
  • 142
  • 10
  • 1
    `global` doesn't fix this, but reassigning to a different name works. – Håken Lid Nov 10 '18 at 20:44
  • @HåkenLid `global` works if you specify a new variable name, but you're right in saying that you don't need to use it if you reassign the values to a different variable. – SahilMak Nov 10 '18 at 21:01