0

I'm trying to make an __init__.py file which will import all functions from *.py files from a directory into a namespace (the directory's name). The logic is shown below:

for f in os.listdir(wd):
    if not f.endswith('.py') or f == '__init__.py':
        continue
    names = get_public_functions(open(wd + f))
    try:
        mod = __import__(f[:-3], fromlist=names)
        for fn in names:
            fun = getattr(mod, fn)
            setattr(sys.modules[__name__], fn, fun)
    except Exception as e: 
        for fn in names:
            setattr(sys.modules[__name__], fn, lambda: str(e))

So, you can observe that if there are syntax error in a file, the functions will still be imported, but they will return the syntax error (as a string).

What's frustrating, is that when there are syntax errors in multiple files, while I'm expecting something like:

mymodule.fn() => error1,
mymodule.fn2() => error1 (these were from the first file),
mymodule.fn3() => error2 etc.

I get only the last error message. I think the error must be in the except block, but I can't figure it. Can anyone help?

1

1 Answer 1

1

You need to bind the value of e to the scope of the lambda you create. Or rather, you want to bind the str(e) result to the lambda:

error = str(e)
for fn in names:
    setattr(sys.modules[__name__], fn, lambda error=error: error

Now each lambda has a keyword parameter storing the then-current value of error. Because the error parameter is a keyword parameter with a default value, your lambdas still work when called with arguments.

The alternative would be to create a new function scope:

def errorfunction(error):
    return lambda: error

error = str(e)
for fn in names:
    setattr(sys.modules[__name__], fn, errorfunction(error)
Sign up to request clarification or add additional context in comments.

5 Comments

Is it possible to make the functions without arguments?
@gg.kaspersky: Not without creating another nested scope. Your function can be called without an argument (it has a default value).
Yes, the default argument solve it. So, was the error because of for? I recall reading something about this...
@gg.kaspersky: The outer loop can assign another exception to e, and you don't call your lambdas until the loop is already done. The lambdas all refer to the same e variable (a cell reference), so they all, in the end, point to the same exception, the last one raised in the loops.
@gg.kaspersky: I've marked your question a dupe where I explained this in more detail; I couldn't find that one at first.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.