public synchronized void execFile(ResourceFile file, JythonScript script)
			throws IllegalStateException {

		if (cleanedUp) {
			throw new IllegalStateException(
				"Ghidra python interpreter has already been cleaned up.");
		}

		initializePythonPath();
		injectScriptHierarchy(script);

		Py.getThreadState().tracefunc = interruptTraceFunction;

		// The Python import system sets the __file__ attribute to the file it's executing
		setVariable("__file__", new PyString(file.getAbsolutePath()));

		// If the remote python debugger is alive, initialize it by calling settrace()
		if (!SystemUtilities.isInDevelopmentMode() && !SystemUtilities.isInHeadlessMode()) {
			if (PyDevUtils.getPyDevSrcDir() != null) {
				try {
					InetAddress localhost = InetAddress.getLocalHost();
					new Socket(localhost, PyDevUtils.PYDEV_REMOTE_DEBUGGER_PORT).close();
					Msg.info(this, "Python debugger found");
					StringBuilder dbgCmds = new StringBuilder();
					dbgCmds.append("import pydevd;");
					dbgCmds.append("pydevd.threadingCurrentThread().__pydevd_main_thread = True;");
					dbgCmds.append("pydevd.settrace(host=\"" + localhost.getHostName() +
						"\", port=" + PyDevUtils.PYDEV_REMOTE_DEBUGGER_PORT + ", suspend=False);");
					exec(dbgCmds.toString());
					Msg.info(this, "Connected to a python debugger.");
				}
				catch (IOException e) {
					Msg.info(this, "Not connected to a python debugger.");
				}
			}
		}

		// Run python file
		execfile(file.getAbsolutePath());
	}
Execute a python file using this interpreter.

@param file The python file to execute.
@param script A PythonScript from which we load state (or null).
@throws IllegalStateException if this interpreter has been cleaned up.
Ghidra/Features/Jython/src/main/java/ghidra/jython/GhidraJythonInterpreter.java