Search code examples
functionvariablespython-3.xscopeflake8

Defining module variables from functions


I've been finally getting into Python, and have noticed something strange, that works in Java, but not in Python.

When I type the following:

fn = ""  # Local filename storage.

def read(filename):
    fn = filename
    return open(filename, 'r').read()

My flake8 linter for Atom gives me the following error:

F841 - local variable 'fn' is assigned to but never used.

I'm assuming this means that the variable is being defined on the def level, and not the module level, which I intend on doing. Please correct me if I'm wrong.

I've searched Google, with multiple wordings, but can't seem to word it in a way that the correct results display...
Any ideas on how I can be able to achieve module-level variable definitions from the function-level?


Solution

  • You can set a module level variable from the function by doing:

    import sys
    
    def read(filename):        
        module = sys.modules[__name__]
        setattr(module, 'fn', filename)
        return open(filename, 'r').read()
    

    However, it's a very strange necessity. Consider to change your architecture.

    UPD: Let's consider an example:

    # module1
    # uncomment it to fix NameError and AttributeError
    # some_var = '' 
    
    def foo(val):
        global some_var
        some_var = val
    
    
    # module2
    from module1 import *
    print(some_var)  # raises NameError: name 'some_var' is not defined
    
    foo('bar')
    print(some_var)  # still raises NameError: name 'some_var' is not defined
    
    
    # module3
    import module1
    print(module1.some_var)  # raises AttributeError: 'module' object has no attribute 'some_var'
    
    foo('bar')
    print(module1.some_var)  # prints 'bar' even without some_var = '' definition in the module1
    

    So, it's not so obvious how global behaves during the import process. I think, that manually doing setattr(module, 'attr_name', value) during the read() call is more clear.