Posts: 50
Threads: 14
Joined: Nov 2016
May-17-2017, 02:01 PM
(This post was last modified: May-17-2017, 02:37 PM by PickyBiker.)
In the simple code below, schedule_last_update in the function check_schedule_file() is seen as a local variable and generates an error at line 15 claiming it is referenced before being assigned a value. It is assigned a value before the main() function. Why isn't that viewed as a global variable?
import os
schedule_file = "/home/pi/sprinkler/schedule.json"
schedule_last_update = os.path.getmtime(schedule_file)
schedule_current_update = schedule_last_update
def main():
print(check_schedule_file())
def check_schedule_file():
print("check_schedule_file")
try:
schedule_current_update = os.path.getmtime("/home/pi/sprinkler/schedule.json")
except:
print("check_schedule_file Error")
if schedule_current_update != schedule_last_update:
schedule_last_update = schedule_current_update
print("schedule changed")
return True
return False
if __name__=="__main__":
main()
Posts: 1,298
Threads: 38
Joined: Sep 2016
Line 22 "main()" is not indented.
You are calling check_schedule_file() without any arguments. You should move your variables into the functions that need them and avoid trying to use globals.
If it ain't broke, I just haven't gotten to it yet.
OS: Windows 10, openSuse 42.3, freeBSD 11, Raspian "Stretch"
Python 3.6.5, IDE: PyCharm 2018 Community Edition
Posts: 50
Threads: 14
Joined: Nov 2016
I indented line 22, but the error still occurs.
I agree that most times I should provide the arguments but occasionally, it's hard to do that. This is a case where that would be easy to do, but I still need to understand why what looks like it should be global, isn't.
Posts: 7,324
Threads: 123
Joined: Sep 2016
May-17-2017, 03:48 PM
(This post was last modified: May-17-2017, 03:50 PM by snippsat.)
(May-17-2017, 02:36 PM)PickyBiker Wrote: , but I still need to understand why what looks like it should be global, isn't. It should look like this, 4 space indent ,argument given to function,no bare except .
import os
def check_schedule_file(schedule_file,schedule_last_update,schedule_current_update):
print("check_schedule_file")
try:
schedule_current_update = os.path.getmtime('bar.json')
except Exception as error:
print(error)
if schedule_current_update != schedule_last_update:
schedule_last_update = schedule_current_update
print("schedule changed")
return True
return False
if __name__ == "__main__":
schedule_file = 'bar.json'
schedule_last_update = os.path.getmtime(schedule_file)
schedule_current_update = schedule_last_update
check_schedule_file(schedule_file, schedule_last_update,schedule_current_update) Now it's only one problem that it do not work.
Try to think of it, bar.json is just run 2 times every time code run,will always be equal.
You have to set start point and save to disk.
Then load getmtine vaule from disk to see if file has changed or not.
Posts: 50
Threads: 14
Joined: Nov 2016
May-17-2017, 04:15 PM
(This post was last modified: May-17-2017, 04:15 PM by PickyBiker.)
Thank you. I learned that placing the variables after the if __name__ == __"main"__: makes it clear they will be executed. You also demonstrated how to send the arguments to the function. I also learned that you can call any function you want following the if __name__ == __"main"__: it does not need to be main()
Am I to understand that there is no way to make a variable global?
Posts: 8,167
Threads: 160
Joined: Sep 2016
May-17-2017, 04:27 PM
(This post was last modified: May-17-2017, 04:28 PM by buran.)
(May-17-2017, 04:15 PM)PickyBiker Wrote: Am I to understand that there is no way to make a variable global?
no, that is not correct. In your code schedule_current_update and schedule_last_update are not considered global, because you try to change their value within the loop. That makes these names in the function local to the def and different from the 'global' ones. in order to be global, you need to add
global schedule_current_update
global schedule_last_update at the top of the function body.
However, as snippsat and sparkz_alot advice you, that's bad programming practice. You should pass these as arguments to the function.
Posts: 50
Threads: 14
Joined: Nov 2016
What a great place to learn. Now I understand the original issue with the variables not being global even though they appeared to be to me.
Please note that I did take seriously the idea of passing the arguments to the functions, I just could not stop wondering WHY those variables were not global. That is now clear up and I will pass the args in my script.
Thank you so much to all of you!
Posts: 12,038
Threads: 487
Joined: Sep 2016
May-17-2017, 04:43 PM
(This post was last modified: May-17-2017, 04:43 PM by Larz60+.)
Python does indeed have globals, but ...
Global variables are considered bad programming in all languages by seasoned programmers.
Here's one reason that kills their use (In my book):
Coupling between various methods (or functions). Assume the following: - Method 1 sets global variable snoot to 4
- Method 2, which uses the contents of snoot, executes method 3 as a thread if snoot equals 4
Upon return from the thread, it checks the content of snoot,
if snoot equals anything other than 4, it prints message: 'method 3 was not executed'
otherwise it prints message: ''method 3 was successfully executed'.
- While the thread in method 2 was running, method 5 changed the global variable snoot to 2.
Method2 will see the '2' when thread completes, thus prints the wrong message.
There are many other reasons you should avoid using globals , see: http://wiki.c2.com/?GlobalVariablesAreBad
Posts: 8,167
Threads: 160
Joined: Sep 2016
|