A safe version of the builtin execfile(). This version will never throw an exception, but instead print helpful error messages to the screen. This only works on pure Python files with the .py extension. Parameters ---------- fname : string
(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False)
| 2930 | return eval(expr, self.user_global_ns, self.user_ns) |
| 2931 | |
| 2932 | def safe_execfile(self, fname, *where, exit_ignore=False, raise_exceptions=False, shell_futures=False): |
| 2933 | """A safe version of the builtin execfile(). |
| 2934 | |
| 2935 | This version will never throw an exception, but instead print |
| 2936 | helpful error messages to the screen. This only works on pure |
| 2937 | Python files with the .py extension. |
| 2938 | |
| 2939 | Parameters |
| 2940 | ---------- |
| 2941 | fname : string |
| 2942 | The name of the file to be executed. |
| 2943 | *where : tuple |
| 2944 | One or two namespaces, passed to execfile() as (globals,locals). |
| 2945 | If only one is given, it is passed as both. |
| 2946 | exit_ignore : bool (False) |
| 2947 | If True, then silence SystemExit for non-zero status (it is always |
| 2948 | silenced for zero status, as it is so common). |
| 2949 | raise_exceptions : bool (False) |
| 2950 | If True raise exceptions everywhere. Meant for testing. |
| 2951 | shell_futures : bool (False) |
| 2952 | If True, the code will share future statements with the interactive |
| 2953 | shell. It will both be affected by previous __future__ imports, and |
| 2954 | any __future__ imports in the code will affect the shell. If False, |
| 2955 | __future__ imports are not shared in either direction. |
| 2956 | |
| 2957 | """ |
| 2958 | fname = Path(fname).expanduser().resolve() |
| 2959 | |
| 2960 | # Make sure we can open the file |
| 2961 | try: |
| 2962 | with fname.open("rb"): |
| 2963 | pass |
| 2964 | except OSError: |
| 2965 | warn('Could not open file <%s> for safe execution.' % fname) |
| 2966 | return |
| 2967 | |
| 2968 | # Find things also in current directory. This is needed to mimic the |
| 2969 | # behavior of running a script from the system command line, where |
| 2970 | # Python inserts the script's directory into sys.path |
| 2971 | dname = str(fname.parent) |
| 2972 | |
| 2973 | with prepended_to_syspath(dname), self.builtin_trap: |
| 2974 | try: |
| 2975 | glob, loc = (where + (None, ))[:2] |
| 2976 | py3compat.execfile( |
| 2977 | fname, glob, loc, |
| 2978 | self.compile if shell_futures else None) |
| 2979 | except SystemExit as status: |
| 2980 | # If the call was made with 0 or None exit status (sys.exit(0) |
| 2981 | # or sys.exit() ), don't bother showing a traceback, as both of |
| 2982 | # these are considered normal by the OS: |
| 2983 | # > python -c'import sys;sys.exit(0)'; echo $? |
| 2984 | # 0 |
| 2985 | # > python -c'import sys;sys.exit()'; echo $? |
| 2986 | # 0 |
| 2987 | # For other exit status, we show the exception unless |
| 2988 | # explicitly silenced, but only in short form. |
| 2989 | if status.code: |