benjammin
benjammin

Reputation: 537

Python - String with timestamp changing

I'm attempting to initialize a string variable in Python using the datetime package. I expect that string to stay the same once it's been initialized, but for some strange reason (at least strange to me), it's changing.

Essentially, when I attempt:

timestamp = datetime.datetime.now().strftime('%m-%d-%Y.%I_%M_%S_%p')
base_directory = "C:\\Users\\Ben\\report_" + timestamp + "\\"
print base_directory #prints C:\Users\Ben\report_02-13-2015_02_02_24_PM
time.sleep(5)
logs_directory = base_directory + "logs\\"

When I go back to use the logs_directory variable, I expect it to be

C:\Users\Ben\report_02-13-2015_02_02_24_PM\logs\

However, instead it is:

C:\Users\Ben\report_02-13-2015_02_02_29_PM\logs\ #!!!

It's as if when I access the logs directory variable, it's going back and reevaluating the base_directory variable again, instead of retrieving the value base_directory has already been set to. Is this intended functionality in Python? I don't it is since I can't seem to trigger this issue from the IDLE shell - it's only occurring when I run my Python program from pydev. However, if this is intended functionality, how do I rewrite my code to achieve the results I'm expecting? Thanks!

I'm not sure if it's relevant, but I'm accessing this variable in nose unit tests. This is in Python 2.7.


UPDATE: Here's some standalone code that better illustrates what's going on. It does in fact look like it is related to nose in some way:

import nose, os, sys, time

timestamp = time.strftime('%m-%d-%Y.%I_%M_%S_%p')
base_directory = "C:\\Users\\Ben\\Desktop\\report_" + timestamp + "\\"
logs_directory = base_directory + "logs\\"

def test_me():
    print base_directory
    print logs_directory

if __name__ == '__main__':
    os.makedirs(base_directory)
    os.makedirs(logs_directory)
    print base_directory
    print logs_directory

    time.sleep(5)

    #Without the nocapture argument, nose will internally log all
    #stdout output, and will not output anything to the console.
    argv = (sys.argv[:])
    argv.insert(1, "--nocapture")
    nose.main(argv=argv)  #This will run test_me()

And here's the output:

C:\Users\Ben\Desktop\report_02-13-2015.04_27_32_PM\
C:\Users\Ben\Desktop\report_02-13-2015.04_27_32_PM\logs\
C:\Users\Ben\Desktop\report_02-13-2015.04_27_37_PM\
C:\Users\Ben\Desktop\report_02-13-2015.04_27_37_PM\logs\

I was expecting:

C:\Users\Ben\Desktop\report_02-13-2015.04_27_32_PM\
C:\Users\Ben\Desktop\report_02-13-2015.04_27_32_PM\logs\
C:\Users\Ben\Desktop\report_02-13-2015.04_27_32_PM\
C:\Users\Ben\Desktop\report_02-13-2015.04_27_32_PM\logs\

What's going on? Why is nose re-evaluating strings that have already been initialized? How do I rewrite my code so that it does what I was expecting? Thanks!

Upvotes: 3

Views: 1702

Answers (1)

jfs
jfs

Reputation: 414795

I can reproduce the issue:

#!/usr/bin/env python
import time

timestamp = time.strftime('%S')

def test_me():
    print('test_me ' + timestamp)
    assert 0

if __name__ == '__main__':
    import nose # $ pip install nose
    print('main ' + timestamp)
    time.sleep(3)
    nose.main()

print('main ' + timestamp) and print('test_me ' + timestamp) show different results.

nose imports the module internally after the sleep and therefore timestamp is different: there are actually two objects __main__.timestamp and module_name.timestamp.

The module should not have a variable global state if it is both run as a script and can be imported. See Executing the main module twice.

Here's an example without nose:

#!/usr/bin/env python
"""Execute main module twice."""
import time

timestamp = time.strftime('%S')

def print_timestamp(prefix):
    print(prefix + timestamp)

if __name__ == '__main__':
    print_timestamp('main')
    time.sleep(3)
    import test_exec_main_twice
    test_exec_main_twice.print_timestamp('module')

Save it to test_exec_main_twice.py file and run.

Upvotes: 3

Related Questions