8000 [po] auto sync · python/python-docs-zh-cn@9f4cdcf · GitHub
[go: up one dir, main page]

Skip to content

Commit 9f4cdcf

Browse files
[po] auto sync
1 parent 0e95e64 commit 9f4cdcf

File tree

2 files changed

+161
-1
lines changed

2 files changed

+161
-1
lines changed

.stat.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"translation": "80.80%", "updated_at": "2025-01-09T07:55:54Z"}
1+
{"translation": "80.80%", "updated_at": "2025-01-09T08:55:34Z"}

howto/logging-cookbook.po

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,6 +2611,109 @@ msgid ""
26112611
"if __name__ == '__main__':\n"
26122612
" main()"
26132613
msgstr ""
2614+
"# 你将在自己的代码中需要这些导入\n"
2615+
"import logging\n"
2616+
"import logging.handlers\n"
2617+
"import multiprocessing\n"
2618+
"\n"
2619+
"# 以下两行导入仅针对本演示\n"
2620+
"from random import choice, random\n"
2621+
"import time\n"
2622+
"\n"
2623+
"#\n"
2624+
"# 因为你会希望为监听进程和工作进程定义日志记录配置,\n"
2625+
"# 这些进程函数将接受一个可调用对象作为 configurer 形参\n"
2626+
"# 用于为进程配置日志记录。 这些函数还将接受一个队列,\n"
2627+
"# 供它们在通信中使用。\n"
2628+
"#\n"
2629+
"# 实际上,你可以根据你的需要任意配置监听进程,但请注意在\n"
2630+
"# 该简单示例中监听进程没有对收到的记录应用层级或过滤逻辑。\n"
2631+
"# 在实践中,你可能会希望在工作进程中执行此逻辑,以避免发送\n"
2632+
"# 将会在进程间被过滤掉的事件。\n"
2633+
"#\n"
2634+
"# 轮转文件的尺寸被设置为很小以便你能方便地查看结果。\n"
2635+
"def listener_configurer():\n"
2636+
" root = logging.getLogger()\n"
2637+
" h = logging.handlers.RotatingFileHandler('mptest.log', 'a', 300, 10)\n"
2638+
" f = logging.Formatter('%(asctime)s %(processName)-10s %(name)s %(levelname)-8s %(message)s')\n"
2639+
" h.setFormatter(f)\n"
2640+
" root.addHandler(h)\n"
2641+
"\n"
2642+
"# 这是监听进程的最高层级循环:等待队列中的日志记录事件\n"
2643+
"# (LogRecords) 并处理它们,当在接受 LogRecord 时收到 None\n"
2644+
"# 则退出。\n"
2645+
"def listener_process(queue, configurer):\n"
2646+
" configurer()\n"
2647+
" while True:\n"
2648+
" try:\n"
2649+
" record = queue.get()\n"
2650+
" if record is None: # 我们发送该值以通知监听进程退出。\n"
2651+
" break\n"
2652+
" logger = logging.getLogger(record.name)\n"
2653+
" logger.handle(record) # 未应用层级或过滤逻辑 —— 直接做! except Exception:\n"
2654+
" import sys, traceback\n"
2655+
" print('Whoops! Problem:', file=sys.stderr)\n"
2656+
" traceback.print_exc(file=sys.stderr)\n"
2657+
"\n"
2658+
"# 用于在本演示中随机选取的数组\n"
2659+
"\n"
2660+
"LEVELS = [logging.DEBUG, logging.INFO, logging.WARNING,\n"
2661+
" logging.ERROR, logging.CRITICAL]\n"
2662+
"\n"
2663+
"LOGGERS = ['a.b.c', 'd.e.f']\n"
2664+
"\n"
2665+
"MESSAGES = [\n"
2666+
" 'Random message #1',\n"
2667+
" 'Random message #2',\n"
2668+
" 'Random message #3',\n"
2669+
"]\n"
2670+
"\n"
2671+
"# 工作进程配置在工作进程开始运行时完成。\n"
2672+
"# 请注意在 Windows 上不能依赖 fork 语义,因此每个进程\n"
2673+
"# 将在启动时运行日志记录配置代码。\n"
2674+
"def worker_configurer(queue):\n"
2675+
" h = logging.handlers.QueueHandler(queue) # 只需要一个处理器\n"
2676+
" root = logging.getLogger()\n"
2677+
" root.addHandler(h)\n"
2678+
" # 发送所有消息,用于演示;未应用其他层级或过滤逻辑。\n"
2679+
" root.setLevel(logging.DEBUG)\n"
2680+
"\n"
2681+
"# 这是工作进程的最高层级循环,它将在结束前以随机间隔\n"
2682+
"# 记录十个事件。\n"
2683+
"# 打印消息只是让你知道它正在做一些事情!\n"
2684+
"def worker_process(queue, configurer):\n"
2685+
" configurer(queue)\n"
2686+
" name = multiprocessing.current_process().name\n"
2687+
" print('Worker started: %s' % name)\n"
2688+
" for i in range(10):\n"
2689+
" time.sleep(random())\n"
2690+
" logger = logging.getLogger(choice(LOGGERS))\n"
2691+
" level = choice(LEVELS)\n"
2692+
" message = choice(MESSAGES)\n"
2693+
" logger.log(level, message)\n"
2694+
" print('Worker finished: %s' % name)\n"
2695+
"\n"
2696+
"# 以下是演示整合各个组件的地方。 创建队列,创建并启动\n"
2697+
"# 监听进程,创建十个工作进程并启动它们,等待它们结束,\n"
2698+
"# 然后向队列发送 None 以通知监听进程退出。\n"
2699+
"def main():\n"
2700+
" queue = multiprocessing.Queue(-1)\n"
2701+
" listener = multiprocessing.Process(target=listener_process,\n"
2702+
" args=(queue, listener_configurer))\n"
2703+
" listener.start()\n"
2704+
" workers = []\n"
2705+
" for i in range(10):\n"
2706+
" worker = multiprocessing.Process(target=worker_process,\n"
2707+
" args=(queue, worker_configurer))\n"
2708+
" workers.append(worker)\n"
2709+
" worker.start()\n"
2710+
" for w in workers:\n"
2711+
" w.join()\n"
2712+
" queue.put_nowait(None)\n"
2713+
" listener.join()\n"
2714+
"\n"
2715+
"if __name__ == '__main__':\n"
2716+
" main()"
26142717

26152718
#: ../../howto/logging-cookbook.rst:1391
26162719
msgid ""
@@ -3671,6 +3774,63 @@ msgid ""
36713774
"finally:\n"
36723775
" listener.stop()"
36733776
msgstr ""
3777+
"# listener.py\n"
3778+
"import json\n"
3779+
"import logging\n"
3780+
"import logging.handlers\n"
3781+
"\n"
3782+
"import pynng\n"
3783+
"\n"
3784+
"DEFAULT_ADDR = \"tcp://localhost:13232\"\n"
3785+
"\n"
3786+
"interrupted = False\n"
3787+
"\n"
3788+
"class NNGSocketListener(logging.handlers.QueueListener):\n"
3789+
"\n"
3790+
" def __init__(self, uri, /, *handlers, **kwargs):\n"
3791+
" # 设置超时以允许中断,并打开一个\n"
3792+
" # 订阅方套接字\n"
3793+
" socket = pynng.Sub0(listen=uri, recv_timeout=500)\n"
3794+
" # b'' 订阅将匹配所有主题\n"
3795+
" topics = kwargs.pop('topics', None) or b''\n"
3796+
" socket.subscribe(topics)\n"
3797+
" # 我们将套接字视为一个队列\n"
3798+
" super().__init__(socket, *handlers, **kwargs)\n"
3799+
"\n"
3800+
" def dequeue(self, block):\n"
3801+
" data = None\n"
3802+
" # 在未被打断且未从套接字接收数据时\n"
3803+
" # 保持循环\n"
3804+
" while not interrupted:\n"
3805+
" try:\n"
3806+
" data = self.queue.recv(block=block)\n"
3807+
" break\n"
3808+
" except pynng.Timeout:\n"
3809+
" pass\n"
3810+
" except pynng.Closed: # 会在你按下 Ctrl-C 时发生\n"
3811+
" break\n"
3812+
" if data is None:\n"
3813+
" return None\n"
3814+
" # 获取从发布方发送的日志记录事件\n"
3815+
" event = json.loads(data.decode('utf-8'))\n"
3816+
" return logging.makeLogRecord(event)\n"
3817+
"\n"
3818+
" def enqueue_sentinel(self):\n"
3819+
" # 在本实现中未被使用,因为套接字并不是\n"
3820+
" # 真正的队列\n"
3821+
" pass\n"
3822+
"\n"
3823+
"logging.getLogger('pynng').propagate = False\n"
3824+
"listener = NNGSocketListener(DEFAULT_ADDR, logging.StreamHandler(), topics=b'')\n"
3825+
"listener.start()\n"
3826+
"print('Press Ctrl-C to stop.')\n"
3827+
"try:\n"
3828+
" while True:\n"
3829+
" pass\n"
3830+
"except KeyboardInterrupt:\n"
3831+
" interrupted = True\n"
3832+
"finally:\n"
3833+
" listener.stop()"
36743834

36753835
#: ../../howto/logging-cookbook.rst:1987
36763836
msgid ""

0 commit comments

Comments
 (0)
0