Clarification regarding abseil library flags

Question:

There is a statement in the abseil documentation that is as follows:

When one Python module imports another, it gains access to the other’s flags. (This behavior is implemented by having all modules share a common, global registry object containing all the flag information.)

When one module imports another — gaining access to the other’s flags — is the reverse true? In other words, does the model being imported also have access to the importing model’s flags? In terms of behaviour, it seems like this is the case. Is the general rule supposed to be that any two python files with some sort of import connection have access to each other’s flags, and that this condition is transitive?

Here are three files that demonstrate the behaviour to which I am referring.

sample.py

from absl import app
from absl import flags
import sample2

FLAGS = flags.FLAGS
flags.DEFINE_string('name', 'Jane Random', 'Your name.')

def main(argv):
  print(FLAGS.name, "is being called in sample.py.")
  print(FLAGS.Flag2) #Flag2 is a flag of sample3.py.
  sample2.Sample()
  
if __name__ == '__main__':
  app.run(main)

sample2.py:

from absl import app
from absl import flags
import sample3

FLAGS = flags.FLAGS
flags.DEFINE_string('Flag1', 'Jane Random', 'Your name.')


class Sample:
    def a_method(self):
        print(FLAGS.name, "is being called in sample2.py.") #sample.py's flags appear to be accessible even though we're not importing from there. 

    def __init__(self):
        self.a_method()
        sample3.Sample()

sample3.py

from absl import app
from absl import flags

FLAGS = flags.FLAGS
flags.DEFINE_string('Flag2', 'This is a sample3.py flag.')

class Sample:
    def a_method(self):
        print(FLAGS.name, "is being called in sample3.py.") #sample.py's flags appear to be accessible even though we're not importing from there. 

    def __init__(self):
        self.a_method()
   
Asked By: Anshul Pattoo

||

Answers:

When you’re settings FLAGS = flags.FLAGS you’re importing flags._flagvalues.FLAGS.

flags._flagvalues.FLAGS is an instance of the FlagValues class defined in _flagvalues.

The reason they can all access the same flags is because they are referring to the same object so any file can refer to the same flags.

If you want to overwrite this you can create a new FlagValues instance and add flags to it by passing it as an argument, e.g.

NEW_FLAGS = flags.FlagValues()
new_flag = flags.DEFINE_string('name', 'default', 'help', flag_values=NEW_FLAGS)

The default arguments to flag_values is always _flag_values.FLAGS

Answered By: Robin Gertenbach

does the model being imported also have access to the importing model’s flags? In terms of behaviour, it seems like this is the case.

I am not sure if this deduction is correct.

In my testing, it seems that:

  • when you import sample2.py into sample.py, sample.py has access to the flags inside sample2.py, but sample2.py doesn’t have access to the flags defined in sample.py:
    • FLAGS.Flag1 in the following example is defined in sample2.py and can be accessed in sample.py.

    • But FLAGS.name defined in sample.py cannot be accessed in sample2.py

If we simplify your example a bit, like:

sample.py

from absl import app
from absl import flags
import sample2

FLAGS = flags.FLAGS
flags.DEFINE_string('name', 'Jane Random', 'Your name.')


def main(argv):
    print(FLAGS.name, "is being called in sample.py.")
    print(FLAGS.Flag1)  # Flag1 is a flag of sample2.py.


if __name__ == '__main__':
    app.run(main)

sample2.py:

from absl import app
from absl import flags

FLAGS = flags.FLAGS
flags.DEFINE_string('Flag1', 'Jane Random', 'Your name.')

print(FLAGS.name, "printing from sample2.py.")

When running the above:

(venv) jcnarasimhan@hadr-crdhost:~/PycharmProjects/hadr/absl_exploration$ python sample.py 
Traceback (most recent call last):
  File "/home/jcnarasimhan/PycharmProjects/hadr/absl_exploration/sample.py", line 3, in <module>
    import sample2
  File "/home/jcnarasimhan/PycharmProjects/hadr/absl_exploration/sample2.py", line 7, in <module>
    print(FLAGS.name, "printing from sample2.py.")
  File "/home/jcnarasimhan/PycharmProjects/hadr/venv/lib/python3.9/site-packages/absl/flags/_flagvalues.py", line 471, in __getattr__
    raise AttributeError(name)
AttributeError: name

Answered By: Jcnars
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.