捕获模块中抛出的错误

如何解决捕获模块中抛出的错误

我使用 gevent 的 WSGIServer 的 serve_forever() 方法和我自己的证书。 像这样:

http_server = WSGIServer(arguments)
http_server.serve_forever()

显然,由于证书不被识别,它会抛出一个错误:

Traceback (most recent call last):
  File "src/gevent/greenlet.py",line 854,in gevent._gevent_cgreenlet.Greenlet.run
  File "/usr/local/lib/python3.7/dist-packages/gevent/baseserver.py",line 34,in _handle_and_close_when_done
    return handle(*args_tuple)
  File "/usr/local/lib/python3.7/dist-packages/gevent/server.py",line 233,in wrap_socket_and_handle
    with _closing_socket(self.wrap_socket(client_socket,**self.ssl_args)) as ssl_socket:
  File "/usr/local/lib/python3.7/dist-packages/gevent/_ssl3.py",line 802,in wrap_socket
    ciphers=ciphers)
  File "/usr/local/lib/python3.7/dist-packages/gevent/_ssl3.py",line 312,in __init__
    raise x
  File "/usr/local/lib/python3.7/dist-packages/gevent/_ssl3.py",line 308,in __init__
    self.do_handshake()
  File "/usr/local/lib/python3.7/dist-packages/gevent/_ssl3.py",line 667,in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1091)
2021-02-25T07:44:54Z <Greenlet at 0x7f5d8ffe5b90: _handle_and_close_when_done(<bound method StreamServer.wrap_socket_and_handle,<bound method StreamServer.do_close of <WSGIServer,(<gevent._socket3.socket [closed] at 0x7f5d9b91a1d)> failed with SSLError

我尝试将文件对象传递给 error_log 参数:

file_with_errors = open("path/to/file","+w")
http_server = WSGIServer(arguments,error_log=file_with_errors)
http_server.serve_forever()

我试着简单地捕捉错误:

http_server = WSGIServer(arguments)
try:
    http_server.serve_forever()
except:
    do_something()

但这些都不起作用,这告诉我错误被抛出并记录在 gevent 模块中的某处。

为了确认这一点,我尝试了:

import io

def func():
    http_server = WSGIServer(arguments)
    http_server.serve_forever()

try:
    _orig_stderr = sys.stderr
    _new_stderr = io.StringIO()
    sys.stderr = _new_stderr
    func()
except:
    file_with_errors = open("path/to/file","+w")
    _new_stderr.seek(0)
    output = _new_stderr.read()
    file_with_errors.write(output)
    sys.stderr = _orig_stderr
    file_with_errors.close()

并发送了一个 KeyboardInterrupt,它起作用了。错误已记录在文件中。

有什么方法可以让我捕获并重定向错误回溯?

解决方法

试试这个:

import logging
import traceback
from wsgiref.simple_server import WSGIServer

logging.basicConfig(filename='test.log',level=logging.DEBUG)
logger = logging.getLogger()

try:
    http_server = WSGIServer(arguments)
    http_server.serve_forever()
except:
    logger.error(traceback.format_exc())
,

这对我有用,它将通过 gevent 控制台发送的任何内容打印到文本文件中。

import logging,sys
from logging import handlers

level = logging.getLevelName('INFO')
log = logging.getLogger('')
log.setLevel(level)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
fh = handlers.RotatingFileHandler('logs/streamlog.txt',maxBytes=(1048576 * 5),backupCount=3)
fh.setFormatter(format)
log.addHandler(fh)
ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)
,
import logging,backupCount=3)
fh.setFormatter(format)
log.addHandler(fh)
ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)
,

根据 gevent uwsgi 文档,error_log 是一个类似文件的对象,具有 write、writelines 和 flush 方法,错误日志将写入其中而不是文件名

log – 如果给定,一个对象具有写入方法的请求 (访问)日志将被写入。如果没有给出,默认为 sys.stderr。 您可以通过 None 来禁用请求日志记录。您可以使用包装器, 围绕例如日志记录,以支持未实现写入的对象 方法。 (如果你传递一个 Logger 实例,或者一般来说 提供日志方法但不提供写入方法,这样的包装器将 自动创建,并将在 INFO 级别登录。)

error_log – 如果给定,则是一个类似文件的对象,带有写、写行和 将写入错误日志的刷新方法。如果不给, 默认为 sys.stderr。您可以通过 None 来禁用错误日志记录 (不建议)。您可以使用包装器,例如记录日志,来 支持没有实现正确方法的对象。这 参数将成为 WSGI 中 wsgi.errors 的值 环境(如果尚未设置)。 (与日志一样,Logger 的包装器 实例等将自动创建并记录到 错误级别。)

你可以试试这个:

logger = logging.getLogger()
file_handler = logging.FileHandler("path/to/file.log")
logger.addHandler(file_handler)
logger.setLevel(logging.INFO)
http_server = WSGIServer(arguments,error_log=logger)
http_server.serve_forever()

另一种解决方案

Gevent 将所有日志写入 stderr,您可以将写入 stderr 的所有内容重定向到您的日志文件,并且由于 sys.stderr 只不过是一个文件对象,因此您无法确定 Gevent 是否没有在 sys.stderr 上使用其他方法。代码中其他地方的 stderr。所以你只需要覆盖 sys.stderr.write 保持一切完好,这样 sys.stderr 的任何其他使用都不会破坏 Gevent 和你的应用程序。

class RedirectStderr(file):

    def __init__(self,*args,**kwargs):
        self._cfg = kwargs.pop('cfg')
        self._log_file = open(self._cfg['access_log_path'],'a')
        super(RedirectStderr,self).__init__(*args,**kwargs)

    def write(self,msg):
        # Just in-case you want to write to both stderr and another log file
        super(RedirectStderr,self).write(msg)

        # Write to another access log file
        self._log_file.write(msg)
        self._log_file.flush()

        # Or use Python's logging facility to log the standard way you log
        # across your project
        log.info(msg)

    def close(self):
        super(RedirectStderr,self).close()
        self._log_file.close()

import sys
sys.stderr = RedirectStderr('path/to/file','w',cfg=cfg)

您可以在此link

中了解更多信息

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res