I'm trying to increment all timestamps (of the form 'HH:MM:SS') in a text file by a number of seconds specified by a command-line parameter to my program.
Here's a simplified version of my effort so far:
import re
from datetime import datetime, timedelta
time_diff = timedelta(seconds=10)
def replace_time(matchobj):
    if matchobj.group(1) not in [None, '']:
       return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")
print re.sub('(\d\d:\d\d:\d\d)', replace_time, "01:27:55")
This works fine: the result of running this is 01:28:05 which is just what I want. 
However, I've heard that I should use global variables as less as possible. So I was wondering if there's a simple way to pass time_diff as an argument to replace_time instead of using a global variable.
I tried the obvious, but it failed:
def replace_time(matchobj, time_diff):
    if matchobj.group(1) not in [None, '']:
       return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")
time_diff = timedelta(seconds=10)
print re.sub('(\d\d:\d\d:\d\d)', replace_time(matchobj, time_diff), "01:27:55")
with this error: NameError: name 'matchobj' is not defined, so I can't pass matchobj directly.
I've looked at the standard re page and standard re howto, but can't find the information I need over there. How can I avoid using a global variable here? Can I somehow pass an extra argument to the replace_time function? Thanks in advance.
The replace method takes three arguments — two are required, the third is optional.
Essentially, you cannot access a global variable if you have defined a local variable of the same name anywhere in the function. Thanks for pointing this out. So, as long as your local scope doesn't assign to a name that exists outside of it, then references in the local scope will use the outside name.
In Python, global keyword allows you to modify the variable outside of the current scope. It is used to create a global variable and make changes to the variable in a local context.
Use of “global†keyword to modify global variable inside a function. If your function has a local variable with same name as global variable and you want to modify the global variable inside function then use 'global' keyword before the variable name at start of function i.e.
You can wrap a function in a closure like this:
def increment_by(time_diff):
    def replace_time(matchobj):
        if matchobj.group(1) not in [None, '']:
            return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")
    return replace_time
time_diff = timedelta(seconds=10)
print re.sub('(\d\d:\d\d:\d\d)', increment_by(time_diff), "01:27:55")
Or you can use a partial from stdlib like this:
from functools import partial
def replace_time(time_diff, matchobj):
    if matchobj.group(1) not in [None, '']:
        return (datetime.strptime(matchobj.group(1), "%H:%M:%S") + time_diff).strftime("%H:%M:%S")
time_diff = timedelta(seconds=10)
print re.sub('(\d\d:\d\d:\d\d)', partial(replace_time, time_diff), "01:27:55")
                        There is nothing wrong with your current approach. time_diff is written to once only and then all future accesses are reads. It effect it is a module wide constant.
You run into problems with shared global state when you have multiple threads accessing an object and at least one of the threads is writing. That's not happening here and you have nothing to be concerned about.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With