Exception thrown when running tf.app.run()
Asked Answered
A

3

4

I am toying around with flags at the moment and came across some weird behavior when using tf.app.run(). The following code snippet should simply print the string given via the command line.

import tensorflow as tf

# command line flags
tf.app.flags.DEFINE_string('mystring', 'Hello World!',
                           '''String to print to console.''')

FLAGS = tf.app.flags.FLAGS


def main():

    print(FLAGS.mystring)

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

During execution, this error is thrown:

Traceback (most recent call last):

File "", line 1, in runfile('/path/flags.py', wdir='/path')

File "/home/abc/anaconda3/envs/tensorflow/lib/python3.5/site-packages/spyder/utils/site/sitecustomize.py", line 710, in runfile execfile(filename, namespace)

File "/home/abc/anaconda3/envs/tensorflow/lib/python3.5/site-packages/spyder/utils/site/sitecustomize.py", line 101, in execfile exec(compile(f.read(), filename, 'exec'), namespace)

File "/path/flags.py", line 19, in tf.app.run()

File "/home/abc/anaconda3/envs/tensorflow/lib/python3.5/site-packages/tensorflow/python/platform/app.py", line 126, in run _sys.exit(main(argv))

TypeError: main() takes 0 positional arguments but 1 was given

...which is strange because I do not give a single argument to main(). However, if I add an underscore def main(_):, it works without any errors.

I couldn't find a doc where this is use of the underscore is described. Does anybody know what happens here? Thank you!

Abacus answered 10/7, 2018 at 13:15 Comment(3)
Your main does not take any arguments.. but tensor flow app.run apparently is trying to pass an argument. "TypeError: main() takes 0 positional arguments but 1 was given"Deflexed
That's right, but I couldn't find the file that defines tf.app.run() to check its return values.Abacus
I suspect (Not a tensor flow expert) that this is so that tensor flow can forward command line arguments to your main. When you put main(_) you store the arguments in a variable named "_" by convention that says you don't intend on using it but your function can now be called with an argument and avoids the error. "_" is a valid variable name :)Deflexed
A
5

The error message I see in Pycharm IDE when I execute your code is clearer.

Traceback (most recent call last):
  File "D:/PycharmProjects/TensorFlow/self.py", line 30, in <module>
    tf.app.run()
  File "D:\\Anaconda\envs\tensorflow\lib\site-packages\tensorflow\python\platform\app.py", 
line 48, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
TypeError: main() takes 0 positional arguments but 1 was given

_sys.exit(main(_sys.argv[:1] + flags_passthrough)) is trying to call our main method with one argument.

This is the run method in app.py

A stripped down version of the run method can be used to test.

import tensorflow as tf
import sys as _sys
from tensorflow.python.platform import flags


# command line flags
tf.app.flags.DEFINE_string('mystring', 'Hello World!',
                           '''String to print to console.''')

FLAGS = tf.app.flags.FLAGS

def run(main=None, argv=None):
  """Runs the program with an optional 'main' function and 'argv' list."""
  f = flags.FLAGS

  # Extract the args from the optional `argv` list.
  args = argv[1:] if argv else None

  # Parse the known flags from that list, or from the command
  # line otherwise.
  # pylint: disable=protected-access
  flags_passthrough = f._parse_flags(args=args)
  # pylint: enable=protected-access

  main = main or _sys.modules['__main__'].main

  print (_sys.argv[:1])

  # Call the main function, passing through any arguments
  # to the final program.
  #_sys.exit(main(_sys.argv[:1] + flags_passthrough))

  # Call the main function with no arguments
  #_sys.exit(main())


def main():
    print(FLAGS.mystring)

if __name__ == '__main__':
    #tf.app.run()
    run()

print(_sys.argv[1:]) prints ['D:/PycharmProjects/TensorFlow/self.py'] since argv[0] is the script name passed to the interpreter.

Abduct answered 10/7, 2018 at 15:46 Comment(3)
+1 for finding the source. Unfortunately, I get an error when trying to execute your script: AttributeError: _parse_flags. No further information is given. Concerning the return value: as I understand it, run() calls the main function with a list as argument, which contains all arguments of argv AND all flags. Does the underscore operator in the main call mean that this exact list is received, but I don't care about it?Abacus
My tensorflow versions is 1.2.1. _parse_flags isn't there in your version. Yes. It is 'I don't care'Abduct
I am using v1.8. Anyway, as my question has been answered, I don't have to be able to run that code snippet.Abacus
O
1

Maybe You can find the answer from this link for explaining how app.py runshow app.py runs

You can also define your main function with def main(argv=None): ..., or like you do def main(_): ..., so this can make it works for you giving the main function parameters.

Oe answered 21/12, 2018 at 2:44 Comment(0)
D
1

I had a similar problem when using cProfile and calling script with

python -m cProfile train.py

Seems like the problem was that tf.app.run called main inside cProfile which wasn't ready for argument passing. In my case the solution was to specify main in tf.app.run():

tf.app.run(main=main)

Don't forget to add fake argument in main like this def main(_):.

Dispel answered 26/12, 2018 at 12:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.