I am using a piece of self-modifying code for a college project.
Here it 开发者_如何学编程is:
import datetime
import inspect
import re
import sys
def main():
# print the time it is last run
lastrun = 'Mon Jun 8 16:31:27 2009'
print "This program was last run at ",
print lastrun
# read in the source code of itself
srcfile = inspect.getsourcefile(sys.modules[__name__])
f = open(srcfile, 'r')
src = f.read()
f.close()
# modify the embedded timestamp
timestamp = datetime.datetime.ctime(datetime.datetime.now())
match = re.search("lastrun = '(.*)'", src)
if match:
src = src[:match.start(1)] + timestamp + src[match.end(1):]
# write the source code back
f = open(srcfile, 'w')
f.write(src)
f.close()
if __name__=='__main__':
main()
Unfortunately, it doesn't work. Error returned:
# This is the script's output
This program is last run at Mon Jun 8 16:31:27 2009
# This is the error message
Traceback (most recent call last):
File "C:\Users\Rui Gomes\Desktop\teste.py", line 30, in <module>
main()
File "C:\Users\Rui Gomes\Desktop\teste.py", line 13, in main
srcfile = inspect.getsourcefile(sys.modules[__name__])
File "C:\Python31\lib\inspect.py", line 439, in getsourcefile
filename = getfile(object)
File "C:\Python31\lib\inspect.py", line 401, in getfile
raise TypeError('{!r} is a built-in module'.format(object))
TypeError: <module '__main__' (built-in)> is a built-in module
I'd be thankful for any solutions.
It runs perfectly when run outside of IDLE -- so therefore the problem is not in your code alone, but in the environment where you are executing it. When you run the erroring portion of your code in IDLE you get this output:
>>> import inspect
>>> sys.modules[__name__]
<module '__main__' from 'C:\Python26\Lib\idlelib\idle.pyw'>
>>> inspect.getsourcefile(sys.modules[__name__])
'C:\\Python26\\Lib\\idlelib\\idle.pyw'
When you run this in IDLE
# read in the source code of itself
srcfile = inspect.getsourcefile(sys.modules[__name__])
f = open(srcfile, 'r')
src = f.read()
f.close()
you are actually trying to modify 'C:\\Python26\\Lib\\idlelib\\idle.pyw'
... which IDLE will not let you do.
The long and the short of it seems to be that what you have written does work: but it cannot be run in IDLE.
You could use the __file__
global attribute to get the current module's source path.
From the 2.6 docs:
__file__
is the pathname of the file from which the module was loaded, if it was loaded from a file. The__file__
attribute is not present for C modules that are statically linked into the interpreter; for extension modules loaded dynamically from a shared library, it is the pathname of the shared library file.
EDIT:
I made the assumption that inspect.getsourcefile() would always throw TypeError when inspecting the __main__
module. That's only the case when run from an interactive interpreter. I stand corrected. Derp.
精彩评论