1

i cant seem to make this work.

I have 2 python files, lets say a.py and b.py

in a.py is this:

def foo():
    global name
    name = "foo"
    import b
    b.bar()

if __name__ == "__main__":
    foo()

in b.py this:

import a

def bar():
    name = a.name
    print(name)

I have three different question in relation to this code:

  1. Why do i get the error: AttributeError: 'module' object has no attribute 'name' I know for certain that b.py cant access the variable defined in the function in b.py but how do i solve this?
  2. does global in this case changes anything? if not, why?
  3. i tried doing name = a.foo.name instead of name = a.name but this doesnt do the trick either and gives me: AttributeError: 'function' object has no attribute 'name', is this even practicable in any case and what did i do wrong?

Thanks for taking the time and sorry if this seems obvious to some of you, i'am still getting into this.

9
  • Where do you define name in a.py? Commented Dec 13, 2015 at 19:59
  • @ozgur yes it's defined in the function foo() in a.py Commented Dec 13, 2015 at 20:03
  • 2
    variables defined inside a function are bound to function's local scope so they are not visible outside of the function. You need to define name somewhere in a.py outside of foo(). Commented Dec 13, 2015 at 20:08
  • @ozgur problem is, later i want to change ´name´ to something else and when i define it outside of the function it will always get reset when importing right? Commented Dec 13, 2015 at 20:13
  • No actually, after foo() is executed once, variable name will remain "foo" in the current process even if you import a again. Commented Dec 13, 2015 at 20:18

2 Answers 2

0

Scripts aren't modules. Its something of a mind bender but when you run python3 a.py, a.py isn't a module (or more properly, its a module named __main__) and it will be reloaded when you import.

Suppose I have c.py

print('hello')
if __name__=="__main__":
    import c

When I run it I get

hello
hello

To illustrate with your example, if I change b.py to

import __main__

def bar():
    name = __main__.name
    print(name)

It works. But only kindof because if somebody imports a you've still got two modules and two copies of the variable.

If you want shared data, they have to be in imported modules, not top level scripts. When I want shared data, I create a separate module that doesn't import anything (or only imports from the standard library) and it is either empty or has defaults for the variables I want to share.

Sign up to request clarification or add additional context in comments.

5 Comments

So i guess shared data would work, i created c.py for a test purpose and only wrote name="foo" into it and made it work, but the thing is, if i want to change the "shared" variable name in c.py to let's say "bar" how would i do this from a.py for example?
If I understand your question, its just c.bar = c.foo. And if you wanted to get rid of the original variable completely it would be del c.foo.
c.py is only name="foo" now, how do i change the variable name out of a.py so there is now name="bar" in c.py, you may wonder why i ask this, its because later on b.py shall get the variable name from c.py with the value name="bar" this is what i understand by "shared data"
Any of the modules can change the variable with c.name = "bar". After that, any module referencing c.name gets "bar".
alright, got it, big thanks for your patience with me!
0

1, 2) The specific purpose of if __name__ == "__main__": is to contain code that will not run when the file is imported. Since foo() is inside that block and nowhere else, the foo function does not run when import a happens; therefore the global name is not assigned to; therefore the a module does not have a name global; therefore b cannot refer to the nonexistent module global with a.name.

  1. a.foo.name cannot fix the problem because, although a.foo exists (there is a foo function defined in the a module at the top level), it does not have a name attribute. The local variables in a function's code are not part of the function object; they exist only temporarily, while the code is running, and are not inherently part of any object. (Even if you call locals(), that creates a new dict, and assigns the local variables as values.)

It is possible to assign attributes to a function - for example, in a.py:

def foo():
    pass
foo.name = "bar"

And such an attribute can be used from outside, including in another module:

# b.py
import a
print(a.foo.name)

But this is entirely orthogonal to what the function actually does, or to using it for any particular purpose.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.