GitHub Viewer
# Copyright (c) 2012 CEF Python, see the Authors file.
# All rights reserved. Licensed under BSD 3-clause license.
# Project website: https://github.com/cztomczak/cefpython
include "cefpython.pyx"
import os
import platform
import re
import traceback
import time
import codecs
def ExceptHook(exc_type, exc_value, exc_trace):
"""Global except hook to exit app cleanly on error.
This hook does the following: in case of exception write it to
the "error.log" file, display it to the console, shutdown CEF
and exit application immediately by ignoring "finally" (_exit()).
"""
print("[CEF Python] ExceptHook: catched exception, will shutdown CEF")
msg = "".join(traceback.format_exception(exc_type, exc_value,
exc_trace))
error_file = GetAppPath("error.log")
encoding = GetAppSetting("string_encoding") or "utf-8"
if type(msg) == bytes:
msg = msg.decode(encoding=encoding, errors="replace")
try:
with codecs.open(error_file, mode="a", encoding=encoding) as fp:
fp.write("\n[%s] %s\n" % (
time.strftime("%Y-%m-%d %H:%M:%S"), msg))
except:
print("[CEF Python] WARNING: failed writing to error file: %s" % (
error_file))
# Convert error message to ascii before printing, otherwise
# you may get error like this:
# | UnicodeEncodeError: 'charmap' codec can't encode characters
msg = msg.encode("ascii", errors="replace")
msg = msg.decode("ascii", errors="replace")
print("\n"+msg)
# There is a strange bug on Mac. Sometimes except message is not
# printed if QuitMessageLoop and Shutdown were called before the print
# message above.
QuitMessageLoop()
Shutdown()
# noinspection PyProtectedMember
os._exit(1)
def UnraisableHook(unraisable):
"""Global unraisable hook, companion to ExceptHook.
sys.unraisablehook is Python's global hook for exceptions that cannot be
propagated to a caller. cefpython's public callbacks are called from CEF's
C++ and declared "noexcept with gil", so an exception escaping one is
reported here instead of unwinding into C++; the same applies to Python's
own unraisable cases (e.g. errors in __del__ or during garbage collection).
Each callback normally forwards exceptions to sys.excepthook itself, so
this hook is the backstop for the ones that escape that guard. By default
sys.unraisablehook only prints to stderr and is easy to miss; assigning
this hook routes such exceptions through ExceptHook so they are written to
"error.log", printed, and CEF is shut down cleanly.
"""
ExceptHook(unraisable.exc_type, unraisable.exc_value,
unraisable.exc_traceback)
cpdef str GetModuleDirectory():
"""Get path to the cefpython module (so/pyd)."""
if hasattr(sys, "frozen"):
# PyInstaller stores collected binaries/data under _MEIPASS (for
# example Contents/Frameworks in a macOS app), which is not always the
# directory containing the frozen executable. Other freezers that do
# not expose _MEIPASS retain the legacy executable-directory layout.
path = getattr(sys, "_MEIPASS", os.path.dirname(sys.executable))
elif platform.system() == "Linux" and os.getenv("CEFPYTHON3_PATH"):
# cefpython3 package __init__.py sets CEFPYTHON3_PATH.
# When cefpython3 is installed as debian package, this
# env variable is the only way of getting valid path.
return os.getenv("CEFPYTHON3_PATH")
elif "__file__" in globals():
path = os.path.dirname(os.path.realpath(__file__))
else:
path = os.getcwd()
if platform.system() == "Windows":
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
path = re.sub(r"[/\\]+$", "", path)
return os.path.abspath(path)
g_GetAppPath_dir = None
cpdef str GetAppPath(file_=None):
"""Get application path."""
# On Windows after downloading file and calling Browser.GoForward(),
# current working directory is set to %UserProfile%.
# Calling os.path.dirname(os.path.realpath(__file__))
# returns for eg. "C:\Users\user\Downloads". A solution
# is to cache path on first call.
if not g_GetAppPath_dir:
if hasattr(sys, "frozen"):
adir = os.path.dirname(sys.executable)
else:
adir = os.getcwd()
global g_GetAppPath_dir
g_GetAppPath_dir = adir
# If file is None return current directory without trailing slash.
if file_ is None:
file_ = ""
# Only when relative path.
if not file_.startswith("/") and not file_.startswith("\\") and (
not re.search(r"^[\w-]+:", file_)):
path = g_GetAppPath_dir + os.sep + file_
if platform.system() == "Windows":
path = re.sub(r"[/\\]+", re.escape(os.sep), path)
path = re.sub(r"[/\\]+$", "", path)
return path
return str(file_)