Issue #14285: Do not catch ImportError from __init__.py in runpy

Initialize package before calling get_loader() for __main__, so that we do
not incorrectly handle ImportError from __init__.py. When runpy is used from
the Python CLI, use an internal exception rather than ImportError, to avoid
catching an unexpected ImportError.

Also simplify message formatting: str() is redundant with %s.

Also fix test_dash_m_error_code_is_one() in test_cmd_line_script, which was
failing because the test package was not in the current directlry, rather
the desired ValueError.
diff --git a/Lib/runpy.py b/Lib/runpy.py
index c4d7cc2..ad4d077 100644
--- a/Lib/runpy.py
+++ b/Lib/runpy.py
@@ -97,27 +97,35 @@
     return None
 
 # Helper to get the loader, code and filename for a module
-def _get_module_details(mod_name):
-    loader = get_loader(mod_name)
-    if loader is None:
-        raise ImportError("No module named %s" % mod_name)
-    if loader.is_package(mod_name):
+def _get_module_details(mod_name, error=ImportError):
+    try:
+        loader = get_loader(mod_name)
+        if loader is None:
+            raise error("No module named %s" % mod_name)
+        ispkg = loader.is_package(mod_name)
+    except ImportError as e:
+        raise error(format(e))
+    if ispkg:
         if mod_name == "__main__" or mod_name.endswith(".__main__"):
-            raise ImportError("Cannot use package as __main__ module")
+            raise error("Cannot use package as __main__ module")
+        __import__(mod_name)  # Do not catch exceptions initializing package
         try:
             pkg_main_name = mod_name + ".__main__"
             return _get_module_details(pkg_main_name)
         except ImportError, e:
-            raise ImportError(("%s; %r is a package and cannot " +
+            raise error(("%s; %r is a package and cannot " +
                                "be directly executed") %(e, mod_name))
-    code = loader.get_code(mod_name)
+    try:
+        code = loader.get_code(mod_name)
+    except ImportError as e:
+        raise error(format(e))
     if code is None:
-        raise ImportError("No code object available for %s" % mod_name)
+        raise error("No code object available for %s" % mod_name)
     filename = _get_filename(loader, mod_name)
     return mod_name, loader, code, filename
 
 
-def _get_main_module_details():
+def _get_main_module_details(error=ImportError):
     # Helper that gives a nicer error message when attempting to
     # execute a zipfile or directory by invoking __main__.py
     main_name = "__main__"
@@ -125,10 +133,13 @@
         return _get_module_details(main_name)
     except ImportError as exc:
         if main_name in str(exc):
-            raise ImportError("can't find %r module in %r" %
+            raise error("can't find %r module in %r" %
                               (main_name, sys.path[0]))
         raise
 
+class _Error(Exception):
+    """Error that _run_module_as_main() should report without a traceback"""
+
 # This function is the actual implementation of the -m switch and direct
 # execution of zipfiles and directories and is deliberately kept private.
 # This avoids a repeat of the situation where run_module() no longer met the
@@ -148,11 +159,12 @@
     """
     try:
         if alter_argv or mod_name != "__main__": # i.e. -m switch
-            mod_name, loader, code, fname = _get_module_details(mod_name)
+            mod_name, loader, code, fname = _get_module_details(
+                mod_name, _Error)
         else:          # i.e. directory or zipfile execution
-            mod_name, loader, code, fname = _get_main_module_details()
-    except ImportError as exc:
-        msg = "%s: %s" % (sys.executable, str(exc))
+            mod_name, loader, code, fname = _get_main_module_details(_Error)
+    except _Error as exc:
+        msg = "%s: %s" % (sys.executable, exc)
         sys.exit(msg)
     pkg_name = mod_name.rpartition('.')[0]
     main_globals = sys.modules["__main__"].__dict__