54

I have a python 2.6 script (yes I know I should upgrade to at least 2.7) that looks like this:

ret_code = 0

def some_func()
  global ret_code
  ...

if __name__ == '__main__':
  global ret_code
  ...

Now I get a warning if I run the code: *SyntaxWarning: name 'ret_code' is assigned to before global declaration global ret_code*

Why do I get this warning?

I can solve the problem by doing so:

def some_func()
      global ret_code
      ...

if __name__ == '__main__':
  global ret_code
  ret_code = 0 #assign 0 here instead of above
  ...

Still that doesn't answer my question. What is wrong with the original code?

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
whomaniac
  • 1,258
  • 4
  • 15
  • 22
  • 14
    Why do you write `global ret_code` in the `if __name__ == '__main__':` block anyway? –  Dec 26 '13 at 12:24
  • 4
    It's wrong for the reasons stated in error message. A variable must be declared global before anything is assigned to it. Actually you don't need to declare names `global` at the module level because they already are that way. It's only needed in functions/methods before you assign a value to them -- so just remove the declaration following the `if __name__ == '__main__':` statement (which is what @delnan meant by his comment). – martineau Dec 26 '13 at 15:27
  • The problem is that you can't use `global` more than once in the same scope. – Pithikos Oct 01 '14 at 17:30
  • 3
    I recommend reopening this question because the specific answer to this question (using `global` underneath `if __name__ == '__main__'` is not related to the linked question or its answer. Furthermore, that other question is sloppier than this one and represents a much more basic Python misunderstanding than this question. My suggestion would be to rename this question `Global variable warning in Python when using the 'global' keyword beneath the test for '__main__'` – Dan Nissenbaum Jan 13 '18 at 02:47
  • Yes, as @DanNissenbaum mentioned it is about using "global" inside "if __name__ == '__main__'". This is not duplicate. – John Prawyn Jan 30 '18 at 08:42

1 Answers1

123

The best direct way to fix this is to remove the global declaration from underneath if __name__ == '__main__':. You don't need it there. Unlike some other languages, an if statement doesn't introduce a new scope in Python - any variables you assign in that block are global, just as they would be without the if there.

This also explains why it is an error: to declare a variable as global, you are not allowed to have used that variable name previously in the same scope (presumably because it would be confusing for the global statement to make assignments before it go to the global variable, and Python doesn't support the same name being both global and local in the same scope). Since the if doesn't introduce a new scope, the first assignment to ret_code is in the same scope as the global declaration under the if; but the global declaration comes later than the assignment, which isn't allowed.

For an even better fix, consider if you can remove the mutable global state from your program entirely, since it usually causes more problems than its worth somewhere down the track. Here, it seems likely that you're using ret_code as a program exit code - ie, you'll be doing sys.exit(ret_code) somewhere - but you're deciding inside a function which exit code to use. Instead, pass enough information back out to the top level code for it to decide which exit code to use.

lvc
  • 34,233
  • 10
  • 73
  • 98
  • 1
    Thanks! My program is a stand alone script. It feels like using global variable would save writing some if statement. – whomaniac Dec 26 '13 at 15:30