Kill execfile(), use exec() instead
diff --git a/Lib/CGIHTTPServer.py b/Lib/CGIHTTPServer.py
index a2d809c..828b092 100644
--- a/Lib/CGIHTTPServer.py
+++ b/Lib/CGIHTTPServer.py
@@ -316,7 +316,7 @@
                         sys.argv.append(decoded_query)
                     sys.stdout = self.wfile
                     sys.stdin = self.rfile
-                    execfile(scriptfile, {"__name__": "__main__"})
+                    exec(open(scriptfile).read(), {"__name__": "__main__"})
                 finally:
                     sys.argv = save_argv
                     sys.stdin = save_stdin
diff --git a/Lib/cProfile.py b/Lib/cProfile.py
index d10b7ab..ae16277 100755
--- a/Lib/cProfile.py
+++ b/Lib/cProfile.py
@@ -180,7 +180,12 @@
 
     if (len(sys.argv) > 0):
         sys.path.insert(0, os.path.dirname(sys.argv[0]))
-        run('execfile(%r)' % (sys.argv[0],), options.outfile, options.sort)
+        fp = open(sys.argv[0])
+        try:
+            script = fp.read()
+        finally:
+            fp.close()
+        run('exec(%r)' % script, options.outfile, options.sort)
     else:
         parser.print_usage()
     return parser
diff --git a/Lib/distutils/core.py b/Lib/distutils/core.py
index bd9b854..d609982 100644
--- a/Lib/distutils/core.py
+++ b/Lib/distutils/core.py
@@ -179,7 +179,7 @@
     keyword args from 'script' to 'setup()', or the contents of the
     config files or command-line.
 
-    'script_name' is a file that will be run with 'execfile()';
+    'script_name' is a file that will be read and run with 'exec()';
     'sys.argv[0]' will be replaced with 'script' for the duration of the
     call.  'script_args' is a list of strings; if supplied,
     'sys.argv[1:]' will be replaced by 'script_args' for the duration of
@@ -217,7 +217,7 @@
             sys.argv[0] = script_name
             if script_args is not None:
                 sys.argv[1:] = script_args
-            execfile(script_name, g, l)
+            exec(open(script_name).read(), g, l)
         finally:
             sys.argv = save_argv
             _setup_stop_after = None
diff --git a/Lib/doctest.py b/Lib/doctest.py
index 0f40818..ec51657 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -2490,7 +2490,7 @@
 
     # Note that tempfile.NameTemporaryFile() cannot be used.  As the
     # docs say, a file so created cannot be opened by name a second time
-    # on modern Windows boxes, and execfile() needs to open it.
+    # on modern Windows boxes, and exec() needs to open and read it.
     srcfilename = tempfile.mktemp(".py", "doctestdebug")
     f = open(srcfilename, 'w')
     f.write(src)
@@ -2504,14 +2504,17 @@
 
         if pm:
             try:
-                execfile(srcfilename, globs, globs)
+                exec(open(srcfilename).read(), globs, globs)
             except:
                 print(sys.exc_info()[1])
                 pdb.post_mortem(sys.exc_info()[2])
         else:
-            # Note that %r is vital here.  '%s' instead can, e.g., cause
-            # backslashes to get treated as metacharacters on Windows.
-            pdb.run("execfile(%r)" % srcfilename, globs, globs)
+            fp = open(srcfilename)
+            try:
+                script = fp.read()
+            finally:
+                fp.close()
+            pdb.run("exec(%r)" % script, globs, globs)
 
     finally:
         os.remove(srcfilename)
diff --git a/Lib/lib-tk/Tkinter.py b/Lib/lib-tk/Tkinter.py
index ef588e8..144be0a 100644
--- a/Lib/lib-tk/Tkinter.py
+++ b/Lib/lib-tk/Tkinter.py
@@ -1688,8 +1688,8 @@
             _default_root = None
     def readprofile(self, baseName, className):
         """Internal function. It reads BASENAME.tcl and CLASSNAME.tcl into
-        the Tcl Interpreter and calls execfile on BASENAME.py and CLASSNAME.py if
-        such a file exists in the home directory."""
+        the Tcl Interpreter and calls exec on the contents of BASENAME.py and
+        CLASSNAME.py if such a file exists in the home directory."""
         import os
         if 'HOME' in os.environ: home = os.environ['HOME']
         else: home = os.curdir
@@ -1702,11 +1702,11 @@
         if os.path.isfile(class_tcl):
             self.tk.call('source', class_tcl)
         if os.path.isfile(class_py):
-            execfile(class_py, dir)
+            exec(open(class_py).read(), dir)
         if os.path.isfile(base_tcl):
             self.tk.call('source', base_tcl)
         if os.path.isfile(base_py):
-            execfile(base_py, dir)
+            exec(open(base_py).read(), dir)
     def report_callback_exception(self, exc, val, tb):
         """Internal function. It reports exception on sys.stderr."""
         import traceback, sys
diff --git a/Lib/optparse.py b/Lib/optparse.py
index 84a6abd..bae1050 100644
--- a/Lib/optparse.py
+++ b/Lib/optparse.py
@@ -874,7 +874,7 @@
 
     def read_file(self, filename, mode="careful"):
         vars = {}
-        execfile(filename, vars)
+        exec(open(filename).read(), vars)
         self._update(vars, mode)
 
     def ensure_value(self, attr, value):
diff --git a/Lib/pdb.py b/Lib/pdb.py
index f408bf3..3bbf76b 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -1164,7 +1164,12 @@
         self._wait_for_mainpyfile = 1
         self.mainpyfile = self.canonic(filename)
         self._user_requested_quit = 0
-        statement = 'execfile( "%s")' % filename
+        fp = open(filename)
+        try:
+            script = fp.read()
+        finally:
+            fp.close()
+        statement = 'exec("%s")' % script
         self.run(statement)
 
 # Simplified interface
diff --git a/Lib/plat-mac/appletrawmain.py b/Lib/plat-mac/appletrawmain.py
index 6f2eacb..5c09e2d 100644
--- a/Lib/plat-mac/appletrawmain.py
+++ b/Lib/plat-mac/appletrawmain.py
@@ -41,7 +41,7 @@
     #
     sys.argv[0] = __file__
     del argvemulator, os, sys, _dir
-    execfile(__file__)
+    exec(open(__file__).read())
 else:
     __file__ = os.path.join(_dir, '__main__.pyc')
     if os.path.exists(__file__):
diff --git a/Lib/plat-mac/bundlebuilder.py b/Lib/plat-mac/bundlebuilder.py
index e833add..d8186c1 100755
--- a/Lib/plat-mac/bundlebuilder.py
+++ b/Lib/plat-mac/bundlebuilder.py
@@ -322,7 +322,12 @@
 import argvemulator, os
 
 argvemulator.ArgvCollector().mainloop()
-execfile(os.path.join(os.path.split(__file__)[0], "%(realmainprogram)s"))
+fp = os.path.join(os.path.split(__file__)[0], "%(realmainprogram)s")
+try:
+    script = fp.read()
+finally:
+    fp.close()
+exec(script)
 """
 
 #
diff --git a/Lib/profile.py b/Lib/profile.py
index 55118b5..cdc2479 100755
--- a/Lib/profile.py
+++ b/Lib/profile.py
@@ -609,7 +609,12 @@
 
     if (len(sys.argv) > 0):
         sys.path.insert(0, os.path.dirname(sys.argv[0]))
-        run('execfile(%r)' % (sys.argv[0],), options.outfile, options.sort)
+        fp = open(sys.argv[0])
+        try:
+            script = fp.read()
+        finally:
+            fp.close()
+        run('exec(%r)' % script, options.outfile, options.sort)
     else:
         parser.print_usage()
     return parser
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index a4ae21a..b430822 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -11,10 +11,6 @@
 warnings.filterwarnings("ignore", "integer argument expected",
                         DeprecationWarning, "unittest")
 
-# count the number of test runs.
-# used to skip running test_execfile() multiple times
-numruns = 0
-
 class Squares:
 
     def __init__(self, max):
@@ -399,57 +395,6 @@
                 return 1 # used to be 'a' but that's no longer an error
         self.assertRaises(TypeError, eval, 'dir()', globals(), C())
 
-    # Done outside of the method test_z to get the correct scope
-    z = 0
-    f = open(TESTFN, 'w')
-    f.write('z = z+1\n')
-    f.write('z = z*2\n')
-    f.close()
-    execfile(TESTFN)
-
-    def test_execfile(self):
-        global numruns
-        if numruns:
-            return
-        numruns += 1
-
-        globals = {'a': 1, 'b': 2}
-        locals = {'b': 200, 'c': 300}
-
-        self.assertEqual(self.__class__.z, 2)
-        globals['z'] = 0
-        execfile(TESTFN, globals)
-        self.assertEqual(globals['z'], 2)
-        locals['z'] = 0
-        execfile(TESTFN, globals, locals)
-        self.assertEqual(locals['z'], 2)
-
-        class M:
-            "Test mapping interface versus possible calls from execfile()."
-            def __init__(self):
-                self.z = 10
-            def __getitem__(self, key):
-                if key == 'z':
-                    return self.z
-                raise KeyError
-            def __setitem__(self, key, value):
-                if key == 'z':
-                    self.z = value
-                    return
-                raise KeyError
-
-        locals = M()
-        locals['z'] = 0
-        execfile(TESTFN, globals, locals)
-        self.assertEqual(locals['z'], 2)
-
-        unlink(TESTFN)
-        self.assertRaises(TypeError, execfile)
-        self.assertRaises(TypeError, execfile, TESTFN, {}, ())
-        import os
-        self.assertRaises(IOError, execfile, os.curdir)
-        self.assertRaises(IOError, execfile, "I_dont_exist")
-
     def test_exec(self):
         g = {}
         exec('z = 1', g)
diff --git a/Lib/test/test_multibytecodec.py b/Lib/test/test_multibytecodec.py
index 32c48fb..c2f34e5 100644
--- a/Lib/test/test_multibytecodec.py
+++ b/Lib/test/test_multibytecodec.py
@@ -49,7 +49,7 @@
         try:
             for enc in ALL_CJKENCODINGS:
                 print('# coding:', enc, file=io.open(TESTFN, 'w'))
-                execfile(TESTFN)
+                exec(open(TESTFN).read())
         finally:
             test_support.unlink(TESTFN)
 
diff --git a/Lib/test/test_pkg.py b/Lib/test/test_pkg.py
index 1a3f2a9..907359b 100644
--- a/Lib/test/test_pkg.py
+++ b/Lib/test/test_pkg.py
@@ -63,7 +63,7 @@
         sys.path.insert(0, root)
         if verbose: print("sys.path =", sys.path)
         try:
-            execfile(fname, globals(), {})
+            exec(open(fname).read(), globals(), {})
         except:
             traceback.print_exc(file=sys.stdout)
     finally:
diff --git a/Lib/test/test_univnewlines.py b/Lib/test/test_univnewlines.py
index ae4c442..7810cae 100644
--- a/Lib/test/test_univnewlines.py
+++ b/Lib/test/test_univnewlines.py
@@ -78,13 +78,6 @@
         data = fp.readlines()
         self.assertEqual(data, DATA_SPLIT[1:])
 
-    def test_execfile(self):
-        namespace = {}
-        execfile(test_support.TESTFN, namespace)
-        func = namespace['line3']
-        self.assertEqual(func.__code__.co_firstlineno, 3)
-        self.assertEqual(namespace['line4'], FATX)
-
 
 class TestNativeNewlines(TestGenericUnivNewlines):
     NEWLINE = None
diff --git a/Lib/trace.py b/Lib/trace.py
index d40f13c..645517a 100644
--- a/Lib/trace.py
+++ b/Lib/trace.py
@@ -773,7 +773,12 @@
                   ignoredirs=ignore_dirs, infile=counts_file,
                   outfile=counts_file)
         try:
-            t.run('execfile(%r)' % (progname,))
+            fp = open(progname)
+            try:
+                script = fp.read()
+            finally:
+                fp.close()
+            t.run('exec(%r)' % (script,))
         except IOError as err:
             _err_exit("Cannot run file %r because: %s" % (sys.argv[0], err))
         except SystemExit:
diff --git a/Lib/user.py b/Lib/user.py
index e550e52..99efd2d 100644
--- a/Lib/user.py
+++ b/Lib/user.py
@@ -12,7 +12,7 @@
     import user
 
 The user module looks for a file .pythonrc.py in the user's home
-directory and if it can be opened, execfile()s it in its own global
+directory and if it can be opened and read, exec()s it in its own global
 namespace.  Errors during this phase are not caught; that's up to the
 program that imports the user module, if it wishes.
 
@@ -42,4 +42,4 @@
     pass
 else:
     f.close()
-    execfile(pythonrc)
+    exec(open(pythonrc).read())