Skip to content

Commit

Permalink
ooooh final ver!
Browse files Browse the repository at this point in the history
  • Loading branch information
HTony03 committed Apr 12, 2024
1 parent 6802d68 commit 0fdf2ad
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 105 deletions.
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,38 @@ and using `logger.inportconfig(inputconfig)` to inport your config
### Exception handler
using the `loggerjava.exceptionhandler.exception(exc)` function to process an Exception

remember to register the defs/classes after you created them

```python
import loggerjava
import loggerjava.exceptionhandler
def test1(a):
print(b)
class test2():
def printa(self):
print(self.b)
loggerjava.exceptionhandler.register_def(test1)
loggerjava.exceptionhandler.register_def(test2)
if __name__ == "__main__":
try:
test1(1)
except Exception as E:
loggerjava.error(loggerjava.exceptionhandler.handler(E))
try:
a = test2
a.printa()
except Exception as E:
loggerjava.error(loggerjava.exceptionhandler.handler(E))
```
#### Output:
```commandline
[20:39:00] [main/ERROR]: NameError: name 'b' is not defined
at <module> (<input>:7)
at test1 (<input>:4)
at <module> (test.py:30)
at test1.test1 (test.py:21)
[20:39:00] [main/ERROR]: AttributeError: 'test2' object has no attribute 'b'
at <module> (test.py:35)
at test2.printa (test.py:25)
```
### Versions

Expand Down
6 changes: 3 additions & 3 deletions loggerjava/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import time
import loggerjava
import loggerjava.exceptionhandler
from loggerjava.exceptionhandler import *

if __name__ == '__main__':

pass

ver = "v0.8.0.dev1"
ver = "v0.8.0"
name = "log"
absolutepath = False
showdetailedtime = False
Expand Down Expand Up @@ -75,7 +75,7 @@ def log(txt, type="i", pos="main", **overrides):
f.close()
if debugmodein:
return _formats.format(timelog, pos, level, txt)
del detailtime, inconsole, debugmodein, timelog, overridename, data
del detailtime, inconsole, debugmodein, timelog


def debug(txt, pos="main", **overrides):
Expand Down
165 changes: 66 additions & 99 deletions loggerjava/exceptionhandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,124 +3,91 @@
import inspect
import os

# 模块级别的变量,用于存储注册的类和函数信息
_database = []

def format_traceback_frame(frame):
filename = frame[0]
lineno = frame[1]
name = frame[2]
text = frame[3]

# 移除文件路径,只保留文件名
filename = os.path.basename(filename)

# 移除函数名前的 'at ',并添加 ' in ' 来更接近 Java 风格
name = name.replace('at ', '').replace(' in ', '')

# 格式化输出
return f" at {name} ({filename}:{lineno})\n"

def register_def(item):
"""
register the classes/defs to the exceptionhander module
:param item: the class/def you created
:return: none
"""
if inspect.isclass(item):
class_name = item.__name__
method_names = [method for method in dir(item) if callable(getattr(item, method)) and method[0] != "_"]
_database.append({
"name": class_name,
"defs": method_names
})
elif inspect.isfunction(item):
func_name = item.__name__
_database.append({
"name": func_name,
"defs": [] # 函数没有内部方法,所以defs为空列表
})
else:
raise ValueError("Only classes and functions can be registered.")


def query_def_ownership(def_name):
"""
check the ownership of def_name
:param def_name: the name of def
:return: the ownership of the def
"""
for entry in _database:
if entry["name"] == def_name or def_name in entry["defs"]:
return entry["name"]
return None # 如果没有找到,返回None

def handler(exc):
"""
the handler of the exceptions
:param exc: the catched Exception
see README.md for the usage of it
:return:
:return: none
"""
# 初始化输出字符串
output = ""

# 捕获异常类型和消息
exc_type = type(exc).__name__
exc_message = str(exc)
formatted_exc = f"{exc_type}: {exc_message}\n"

tb = exc.__traceback__
frames = traceback.extract_tb(tb)

for frame in frames:
filename, lineno, name, text = frame
filename = os.path.basename(filename)

# 添加异常类型和消息到输出字符串
output += f"{exc_type}: {exc_message}\n"
cls = query_def_ownership(name)
#module_name = ""
#print(cls)
if cls is None:
formatted_frame = f" at {name} ({filename}:{lineno})\n"
else:
#formatted_frame = f" at {module_name}.{cls}.{name} ({filename}:{lineno})\n"
formatted_frame = f" at {cls}.{name} ({filename}:{lineno})\n"

# 提取堆栈跟踪信息
tb = traceback.extract_tb(exc.__traceback__)
formatted_exc += formatted_frame

# 遍历堆栈帧并添加到输出字符串
for frame in tb:
output += format_traceback_frame(frame)
return formatted_exc

return output


def handler2(Exception):
# 获取异常的类型、值和traceback对象
exc_type, exc_value, exc_traceback = sys.exc_info()
# 格式化异常信息为字符串列表
tb_list = traceback.format_exception(exc_type, exc_value, exc_traceback)
# 将列表中的字符串连接起来形成完整的调用栈信息
tb_str = ''.join(tb_list)
# 打印调用栈信息
print(f"捕获到异常: {Exception}\n调用栈信息:\n{tb_str}")
print(exc_type.__name__)
print(exc_value)
print(exc_traceback)
#print(tb_list)
print(tb_str)

exception_type_full_str = f"{type(Exception).__module__}.{type(Exception).__name__}"
line = exception_type_full_str+": "+str(Exception)+"\n at"
print(line)
class a():
def __init__(self):
self.a = 1

def p(self):
print(self.b)
register_def(a)
if __name__ == "__main__":
pass
#hmm wat?
"""

try:
print(a)
except Exception as e:
print(handler(e))
"""
"""
exception_type_name = type(e).__name__
# 将异常类型的名称转化为字符串(实际上已经是字符串了)
exception_type_str = str(exception_type_name)
print(f"捕获到异常类型: {exception_type_str}")
exception_type_full_str = f"{type(e).__module__}.{type(e).__name__}"
print(f"完整的异常类型字符串: {exception_type_full_str}")
tb = traceback.extract_tb(e.__traceback__)
# 通常,最后一个元素是异常发生的位置
last_frame = tb[-1]
# 获取函数名和模块名
func_name = last_frame[2]
module_name = last_frame[0]
print("捕获到异常:")
print(f"异常类型: {type(e).__name__}")
print(f"异常信息: {e}")
print("调用栈信息:")
# 打印完整的堆栈跟踪信息
for frame in tb:
filename, line_number, function_name, text = frame
print(f"{module_name}.{function_name} (文件 {filename}, 行 {line_number})")
print(f" {text.strip()}")
tb = e.__traceback__
# 提取堆栈跟踪信息
stack_info = traceback.extract_tb(tb)
# 格式化堆栈跟踪信息以更接近Java的格式
formatted_tb = []
for frame in stack_info:
filename, line_number, function_name, text = frame
# 假设模块名就是文件名去掉.py后缀(这通常不是完全准确的,但在这里作为示例)
module_name = filename.rsplit('.', 1)[0].replace('/', '.') if '.' in filename else '__main__'
formatted_tb.append(f"{module_name}.{function_name} (文件 {filename}, 行 {line_number})")
formatted_tb.append(f" {text.strip()}")
# 打印异常类型和消息
print("捕获到异常:")
print(f"异常类型: {type(e).__name__}")
print(f"异常信息: {e}")
# 打印格式化后的堆栈跟踪信息
print("调用栈信息:")
for line in formatted_tb:
print(line)
"""
sa = a()
sa.p()
except Exception as E:
print(handler4(E))
#hmm wat?
12 changes: 12 additions & 0 deletions loggerjava/test_loggerjava.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# import pytest
import time

import loggerjava.exceptionhandler

"""
class MyTestCase(unittest.TestCase):
def test_something(self):
Expand Down Expand Up @@ -45,6 +47,16 @@ def testin():
assert logger.log("testoverride", type="d",
showdetailedtime=True) == "[" + time.asctime() + "] [main/debug]: testoverride\n"
assert logger.warn("testoverride", showdetailedtime=True) == "[" + time.asctime() + "] [main/WARN]: testoverride\n"
try:
def test1(a):
print(b)
test1(1)
except Exception as e:
a = loggerjava.exceptionhandler.handler(e)
assert a == "NameError: name 'b' is not defined\n at testin (test_loggerjava.py:53)\n at test1 (test_loggerjava.py:52)\n"
assert logger.warn(loggerjava.exceptionhandler.handler(e)) == "[" + str(time.localtime().tm_hour).rjust(2, "0") + ":" + \
str(time.localtime().tm_min).rjust(2, "0") + ":" + str(time.localtime().tm_sec).rjust(2,
"0") + "] [main/WARN]: %s\n"%a


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "loggerjava"
version = "v0.8.0.dev1"
version = "v0.8.0"
authors = [
{ name="HTony03", email="[email protected]" },
]
Expand Down

0 comments on commit 0fdf2ad

Please sign in to comment.