0001 """Routine to "compile" a .py file to a .pyc (or .pyo) file. 0002 0003 This module has intimate knowledge of the format of .pyc files. 0004 """ 0005 0006 import __builtin__ 0007 import imp 0008 import marshal 0009 import os 0010 import sys 0011 import traceback 0012 0013 MAGIC = imp.get_magic() 0014 0015 __all__ = ["compile", "main", "PyCompileError"] 0016 0017 0018 class PyCompileError(Exception): 0019 """Exception raised when an error occurs while attempting to 0020 compile the file. 0021 0022 To raise this exception, use 0023 0024 raise PyCompileError(exc_type,exc_value,file[,msg]) 0025 0026 where 0027 0028 exc_type: exception type to be used in error message 0029 type name can be accesses as class variable 0030 'exc_type_name' 0031 0032 exc_value: exception value to be used in error message 0033 can be accesses as class variable 'exc_value' 0034 0035 file: name of file being compiled to be used in error message 0036 can be accesses as class variable 'file' 0037 0038 msg: string message to be written as error message 0039 If no value is given, a default exception message will be given, 0040 consistent with 'standard' py_compile output. 0041 message (or default) can be accesses as class variable 'msg' 0042 0043 """ 0044 0045 def __init__(self, exc_type, exc_value, file, msg=''): 0046 exc_type_name = exc_type.__name__ 0047 if exc_type is SyntaxError: 0048 tbtext = ''.join(traceback.format_exception_only(exc_type, exc_value)) 0049 errmsg = tbtext.replace('File "<string>"', 'File "%s"' % file) 0050 else: 0051 errmsg = "Sorry: %s: %s" % (exc_type_name,exc_value) 0052 0053 Exception.__init__(self,msg or errmsg,exc_type_name,exc_value,file) 0054 0055 self.exc_type_name = exc_type_name 0056 self.exc_value = exc_value 0057 self.file = file 0058 self.msg = msg or errmsg 0059 0060 def __str__(self): 0061 return self.msg 0062 0063 0064 # Define an internal helper according to the platform 0065 if os.name == "mac": 0066 import MacOS 0067 def set_creator_type(file): 0068 MacOS.SetCreatorAndType(file, 'Pyth', 'PYC ') 0069 else: 0070 def set_creator_type(file): 0071 pass 0072 0073 def wr_long(f, x): 0074 """Internal; write a 32-bit int to a file in little-endian order.""" 0075 f.write(chr( x & 0xff)) 0076 f.write(chr((x >> 8) & 0xff)) 0077 f.write(chr((x >> 16) & 0xff)) 0078 f.write(chr((x >> 24) & 0xff)) 0079 0080 def compile(file, cfile=None, dfile=None, doraise=False): 0081 """Byte-compile one Python source file to Python bytecode. 0082 0083 Arguments: 0084 0085 file: source filename 0086 cfile: target filename; defaults to source with 'c' or 'o' appended 0087 ('c' normally, 'o' in optimizing mode, giving .pyc or .pyo) 0088 dfile: purported filename; defaults to source (this is the filename 0089 that will show up in error messages) 0090 doraise: flag indicating whether or not an exception should be 0091 raised when a compile error is found. If an exception 0092 occurs and this flag is set to False, a string 0093 indicating the nature of the exception will be printed, 0094 and the function will return to the caller. If an 0095 exception occurs and this flag is set to True, a 0096 PyCompileError exception will be raised. 0097 0098 Note that it isn't necessary to byte-compile Python modules for 0099 execution efficiency -- Python itself byte-compiles a module when 0100 it is loaded, and if it can, writes out the bytecode to the 0101 corresponding .pyc (or .pyo) file. 0102 0103 However, if a Python installation is shared between users, it is a 0104 good idea to byte-compile all modules upon installation, since 0105 other users may not be able to write in the source directories, 0106 and thus they won't be able to write the .pyc/.pyo file, and then 0107 they would be byte-compiling every module each time it is loaded. 0108 This can slow down program start-up considerably. 0109 0110 See compileall.py for a script/module that uses this module to 0111 byte-compile all installed files (or all files in selected 0112 directories). 0113 0114 """ 0115 f = open(file, 'U') 0116 try: 0117 timestamp = long(os.fstat(f.fileno()).st_mtime) 0118 except AttributeError: 0119 timestamp = long(os.stat(file).st_mtime) 0120 codestring = f.read() 0121 f.close() 0122 if codestring and codestring[-1] != '\n': 0123 codestring = codestring + '\n' 0124 try: 0125 codeobject = __builtin__.compile(codestring, dfile or file,'exec') 0126 except Exception,err: 0127 py_exc = PyCompileError(err.__class__,err.args,dfile or file) 0128 if doraise: 0129 raise py_exc 0130 else: 0131 sys.stderr.write(py_exc.msg) 0132 return 0133 if cfile is None: 0134 cfile = file + (__debug__ and 'c' or 'o') 0135 fc = open(cfile, 'wb') 0136 fc.write('\0\0\0\0') 0137 wr_long(fc, timestamp) 0138 marshal.dump(codeobject, fc) 0139 fc.flush() 0140 fc.seek(0, 0) 0141 fc.write(MAGIC) 0142 fc.close() 0143 set_creator_type(cfile) 0144 0145 def main(args=None): 0146 """Compile several source files. 0147 0148 The files named in 'args' (or on the command line, if 'args' is 0149 not specified) are compiled and the resulting bytecode is cached 0150 in the normal manner. This function does not search a directory 0151 structure to locate source files; it only compiles files named 0152 explicitly. 0153 0154 """ 0155 if args is None: 0156 args = sys.argv[1:] 0157 for filename in args: 0158 try: 0159 compile(filename, doraise=True) 0160 except PyCompileError,err: 0161 sys.stderr.write(err.msg) 0162 0163 if __name__ == "__main__": 0164 main() 0165
Generated by PyXR 0.9.4