0

The title might be misleading or inaccurate, so please correct me if I'm wrong.

I have a package structured like this:

common
    __init__.py
foo.py

And here are the codes:

common/__init__.py

name = 'name_common'

def print_current_file_name():
    print('current file name: ' +  __file__)

def print_name():
    print('name is: ' + eval('name'))

foo.py

from common import print_current_file_name, print_name

name = 'name_foo'

if __name__ == '__main__':
    print_current_file_name()
    print_name()

If I do this:

>>> python foo.py

I'll get this:

current file name: /tmp/common/__init__.py
name is: name_common

But I expect the results to be:

current file name: /tmp/common/foo.py
name is: name_foo

What did I miss? How can I make this right? I don't even know which keywords should I google...

The use of eval is weird, but these codes are just for demonstration purpose only.

amigcamel
  • 1,879
  • 1
  • 22
  • 36

2 Answers2

0

That's not at all how variables work in Python, or in any language I'm aware of.

The global scope of a function is always where it is defined, not where it is executed. There is no way for print_name to access the value of name in foo.py.

Rather, you should pass it in as a parameter. Or, depending on what you actually want to do, you might want to create a class that defines the value of name at class level.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I agree, but I'm just wondering if there's any way to achieve this (without using `class`) – amigcamel Apr 13 '17 at 15:36
  • 2
    @amigcamel You are describing a dynamically scoped language (prominent examples are Scheme and shell); Python is statically scoped. – chepner Apr 13 '17 at 15:43
0

Actually, this is possible.

I Found a similar question:
How to use inspect to get the caller's info from callee in Python?

And I think this is what the built-in library inspect comes for.

common/__init__.py

from os.path import abspath
import inspect


name = 'name_common'

def print_current_file_name():

    print('current file name: ' + abspath(inspect.getfile(inspect.currentframe().f_back)))
    # or
    print('current file name: ' + abspath(inspect.currentframe().f_back.f_globals['__file__']))

def print_name():
    print('name is: ' + inspect.currentframe().f_back.f_globals['name'])

Finally,

$ python foo.py
current file name: /tmp/common/foo.py
name is: name_foo
amigcamel
  • 1,879
  • 1
  • 22
  • 36