diff --git a/library/signal.po b/library/signal.po index ca7802204d..549c342839 100644 --- a/library/signal.po +++ b/library/signal.po @@ -559,6 +559,11 @@ msgid "" "interval timer specified by *which* can be cleared by setting *seconds* to " "zero." msgstr "" +"設定由 *which* 指定的間隔計時器(:const:`signal.ITIMER_REAL`、:const:`signal." +"ITIMER_VIRTUAL` 或 :const:`signal.ITIMER_PROF` 之一)並在*seconds*\\ (接受浮" +"點數,與 :func:`alarm` 不同)之後啟動,在之後的每 *interval* 秒啟動一次(如" +"果 *interval* 非零)。*which* 指定的間隔計時器可透過將 *seconds* 設定為零來清" +"除它。" #: ../../library/signal.rst:490 msgid "" @@ -567,20 +572,24 @@ msgid "" "deliver :const:`SIGALRM`, :const:`signal.ITIMER_VIRTUAL` sends :const:" "`SIGVTALRM`, and :const:`signal.ITIMER_PROF` will deliver :const:`SIGPROF`." msgstr "" +"當間隔計時器啟動時,一個訊號會被傳送給行程。傳送的訊號取決於使用的計時器;:" +"const:`signal.ITIMER_REAL` 會傳送 :const:`SIGALRM`,:const:`signal." +"ITIMER_VIRTUAL` 會傳送 :const:`SIGVTALRM`,而 :const:`signal.ITIMER_PROF` 會" +"傳送 :const:`SIGPROF`。" #: ../../library/signal.rst:496 msgid "The old values are returned as a tuple: (delay, interval)." -msgstr "" +msgstr "舊值會以一個元組回傳:(delay, interval)。" #: ../../library/signal.rst:498 msgid "" "Attempting to pass an invalid interval timer will cause an :exc:" "`ItimerError`." -msgstr "" +msgstr "嘗試傳入無效的間隔計時器會導致 :exc:`ItimerError`。" #: ../../library/signal.rst:506 msgid "Returns current value of a given interval timer specified by *which*." -msgstr "" +msgstr "回傳由 *which* 指定之間隔計時器的當前值。" #: ../../library/signal.rst:513 msgid "" @@ -589,6 +598,8 @@ msgid "" "a library to wakeup a poll or select call, allowing the signal to be fully " "processed." msgstr "" +"設定喚醒檔案描述器為 *fd*。當接收到訊號時,訊號編號會以單一位元組寫入 fd。這" +"可被函式庫用來喚醒輪詢 (wakeup a poll) 或 select 呼叫,讓訊號得以完全處理。" #: ../../library/signal.rst:518 msgid "" @@ -597,6 +608,9 @@ msgid "" "*fd* must be non-blocking. It is up to the library to remove any bytes from " "*fd* before calling poll or select again." msgstr "" +"回傳舊的喚醒 fd(如果檔案描述器喚醒未啟用,則回傳 -1)。如果 *fd* 為 -1,則會" +"停用檔案描述器喚醒。如果不是 -1,*fd* 必須是非阻塞的。在再次呼叫輪詢或 " +"select 之前,由函式庫來決定是否移除 *fd* 中的任何位元組。" #: ../../library/signal.rst:523 ../../library/signal.rst:578 msgid "" @@ -605,6 +619,8 @@ msgid "" "call it from other threads will cause a :exc:`ValueError` exception to be " "raised." msgstr "" +"當啟用執行緒時,這個函式只能從\\ :ref:`主直譯器 `\\ 的主" +"執行緒來呼叫;嘗試從其他執行緒呼叫它將會引發 :exc:`ValueError` 例外。" #: ../../library/signal.rst:528 msgid "" @@ -612,6 +628,8 @@ msgid "" "the fd to wake up when a signal arrives, but then they differ in how they " "determine *which* signal or signals have arrived." msgstr "" +"使用這個函式有兩種常見的方式。在這兩種方法中,當訊號抵達時,你都要使用 fd 來" +"喚醒,但它們的不同之處在於如何判斷\\ *哪個或哪些*\\ 訊號有抵達。" #: ../../library/signal.rst:533 msgid "" @@ -623,6 +641,11 @@ msgid "" "you should set ``warn_on_full_buffer=True``, which will at least cause a " "warning to be printed to stderr when signals are lost." msgstr "" +"在第一種方法中,我們從 fd 的緩衝區中讀取資料,而位元組值則提供訊號編號。這個" +"方法很簡單,但在少數情況下可能會遇到問題:一般來說,fd 的緩衝區空間有限,如果" +"太多訊號來得太快,那麼緩衝區可能會滿,而有些訊號可能會遺失。如果你使用這種方" +"法,那麼你應該設定 ``warn_on_full_buffer=True``,這至少會在訊號丟失時將警告印" +"出到 stderr。" #: ../../library/signal.rst:542 msgid "" @@ -633,10 +656,14 @@ msgid "" "``warn_on_full_buffer=False``, so that your users are not confused by " "spurious warning messages." msgstr "" +"在第二種方法中,我們\\ *只會*\\ 將喚醒 fd 用於喚醒,而忽略實際的位元組值。在" +"這種情況下,我們只在乎 fd 的緩衝區是空或非空;即便緩衝區滿了也不代表有問題。" +"如果你使用這種方法,那麼你應該設定 ``warn_on_full_buffer=False``,這樣你的使" +"用者就不會被虛假的警告訊息所混淆。" #: ../../library/signal.rst:549 msgid "On Windows, the function now also supports socket handles." -msgstr "" +msgstr "在 Windows 上,此功能現在也支援 socket 處理程式。" #: ../../library/signal.rst:552 msgid "Added ``warn_on_full_buffer`` parameter." @@ -648,10 +675,12 @@ msgid "" "calls will be restarted when interrupted by signal *signalnum*, otherwise " "system calls will be interrupted. Returns nothing." msgstr "" +"改變系統呼叫重新啟動的行為:如果 *flag* 是 :const:`False`,系統呼叫會在被訊" +"號 *signalnum* 中斷時重新啟動,否則系統呼叫會被中斷。不會回傳任何東西。" #: ../../library/signal.rst:563 msgid "See the man page :manpage:`siginterrupt(3)` for further information." -msgstr "更多資訊請見 :manpage:`siginterrupt(3)` 手冊頁。" +msgstr "更多資訊請見 :manpage:`siginterrupt(3)` 線上手冊。" #: ../../library/signal.rst:565 msgid "" @@ -659,6 +688,8 @@ msgid "" "restart behaviour to interruptible by implicitly calling :c:func:`!" "siginterrupt` with a true *flag* value for the given signal." msgstr "" +"請注意,使用 :func:`signal` 安裝訊號處理程式,會透過隱式呼叫 :c:func:`!" +"siginterrupt` 來將重新啟動的行為重設為可中斷,且指定訊號的 *flag* 值為 true。" #: ../../library/signal.rst:572 msgid "" @@ -669,6 +700,10 @@ msgid "" "`getsignal` above). (See the Unix man page :manpage:`signal(2)` for further " "information.)" msgstr "" +"將訊號 *signalnum* 的處理程式設定為函式 *handler*。*handler* 可以是帶兩個引數" +"的可呼叫 Python 物件(見下面),或是特殊值 :const:`signal.SIG_IGN` 或 :const:" +"`signal.SIG_DFL` 之一。先前的訊號處理程式將會被回傳(請參閱上面 :func:" +"`getsignal` 的說明)。(更多資訊請參閱 Unix 線上手冊 :`signal(2)`)。" #: ../../library/signal.rst:583 msgid "" @@ -677,6 +712,9 @@ msgid "" "objects, see the :ref:`description in the type hierarchy ` or " "see the attribute descriptions in the :mod:`inspect` module)." msgstr "" +"*handler* 被呼叫時有兩個引數:訊號編號和目前的堆疊 frame(``None`` 或一個 " +"frame 物件;關於 frame 物件的描述,請參閱\\ :ref:`型別階層中的描述 `\\ 或 :mod:`inspect` 模組中的屬性描述)。" #: ../../library/signal.rst:588 msgid "" @@ -687,6 +725,11 @@ msgid "" "an :exc:`AttributeError` will be raised if a signal name is not defined as " "``SIG*`` module level constant." msgstr "" +"在 Windows 上,:func:`signal` 只能在使用 :const:`SIGABRT`、:const:`SIGFPE`、:" +"const:`SIGILL`、:const:`SIGINT`、:const:`SIGSEGV`、:const:`SIGTERM` 或 :" +"const:`SIGBREAK` 時呼叫。在其他情況下會引發 :exc:`ValueError`。請注意,並非所" +"有系統都定義相同的訊號名稱;如果訊號名稱沒有被定義為 ``SIG*`` 模組層級常數," +"則會引發 :exc:`AttributeError` 錯誤。" #: ../../library/signal.rst:599 msgid "" @@ -694,10 +737,12 @@ msgid "" "thread (i.e., the signals which have been raised while blocked). Return the " "set of the pending signals." msgstr "" +"檢查待傳送至呼叫執行緒的訊號集合(即阻檔時已被提出的訊號)。回傳待定訊號的集" +"合。" #: ../../library/signal.rst:605 msgid "See the man page :manpage:`sigpending(2)` for further information." -msgstr "更多資訊請見 :manpage:`sigpending(2)` 手冊頁。" +msgstr "更多資訊請見 :manpage:`sigpending(2)` 線上手冊。" #: ../../library/signal.rst:607 msgid "See also :func:`pause`, :func:`pthread_sigmask` and :func:`sigwait`." @@ -710,16 +755,20 @@ msgid "" "signal (removes it from the pending list of signals), and returns the signal " "number." msgstr "" +"暫停呼叫執行緒的執行,直到送出訊號集合 *sigset* 中指定的一個訊號。函式接受訊" +"號(將其從待定訊號清單中移除),並回傳訊號編號。" #: ../../library/signal.rst:620 msgid "See the man page :manpage:`sigwait(3)` for further information." -msgstr "更多資訊請見 :manpage:`sigwait(3)` 手冊頁。" +msgstr "更多資訊請見 :manpage:`sigwait(3)` 線上手冊。" #: ../../library/signal.rst:622 msgid "" "See also :func:`pause`, :func:`pthread_sigmask`, :func:`sigpending`, :func:" "`sigwaitinfo` and :func:`sigtimedwait`." msgstr "" +"另也請見 :func:`pause`、:func:`pthread_sigmask`、:func:`sigpending`、:func:" +"`sigwaitinfo` 和 :func:`sigtimedwait`。" #: ../../library/signal.rst:630 msgid "" @@ -731,6 +780,11 @@ msgid "" "handler is not called for the delivered signal. The function raises an :exc:" "`InterruptedError` if it is interrupted by a signal that is not in *sigset*." msgstr "" +"暫停呼叫執行緒的執行,直到送出訊號集合 *sigset* 中指定的一個訊號。該函式接受" +"訊號,並將其從待定訊號清單中移除。如果 *sigset* 中的一個訊號已經是呼叫執行緒" +"的待定訊號,函式會立即回傳該訊號的相關資訊。對於已傳送的訊號,訊號處理程式不" +"會被呼叫。如果被不在 *sigset* 中的訊號中斷,函式會引發 :exc:" +"`InterruptedError`。" #: ../../library/signal.rst:639 msgid "" @@ -739,10 +793,13 @@ msgid "" "`si_errno`, :attr:`si_pid`, :attr:`si_uid`, :attr:`si_status`, :attr:" "`si_band`." msgstr "" +"回傳值是一個物件,代表 :c:type:`siginfo_t` 結構所包含的資料,即 :attr:" +"`si_signo`、:attr:`si_code`、:attr:`si_errno`、:attr:`si_pid`、:attr:" +"`si_uid`、:attr:`si_status`、:attr:`si_band`。" #: ../../library/signal.rst:646 msgid "See the man page :manpage:`sigwaitinfo(2)` for further information." -msgstr "更多資訊請見 :manpage:`sigwaitinfo(2)` 手冊頁。" +msgstr "更多資訊請見 :manpage:`sigwaitinfo(2)` 線上手冊。" #: ../../library/signal.rst:648 msgid "See also :func:`pause`, :func:`sigwait` and :func:`sigtimedwait`." @@ -754,6 +811,8 @@ msgid "" "the signal handler does not raise an exception (see :pep:`475` for the " "rationale)." msgstr "" +"現在如果被不在 *sigset* 中的訊號中斷,且訊號處理程式沒有引發例外,則會重試函" +"式(理由請參閱 :pep:`475`)。" #: ../../library/signal.rst:660 msgid "" @@ -761,10 +820,12 @@ msgid "" "specifying a timeout. If *timeout* is specified as ``0``, a poll is " "performed. Returns :const:`None` if a timeout occurs." msgstr "" +"類似 :func:`sigwaitinfo`,但需要額外的 *timeout* 引數指定逾時時間。如果 " +"*timeout* 指定為 ``0``,會執行輪詢。如果發生逾時則會回傳 :const:`None`。" #: ../../library/signal.rst:666 msgid "See the man page :manpage:`sigtimedwait(2)` for further information." -msgstr "更多資訊請見 :manpage:`sigtimedwait(2)` 手冊頁。" +msgstr "更多資訊請見 :manpage:`sigtimedwait(2)` 線上手冊。" #: ../../library/signal.rst:668 msgid "See also :func:`pause`, :func:`sigwait` and :func:`sigwaitinfo`." @@ -776,6 +837,8 @@ msgid "" "a signal not in *sigset* and the signal handler does not raise an exception " "(see :pep:`475` for the rationale)." msgstr "" +"現在如果被不在 *sigset* 中的訊號中斷,且訊號處理程式沒有引發例外,則會使用重" +"新計算的 *timeout* 重試函式(理由請參閱 :pep:`475`)。" #: ../../library/signal.rst:681 msgid "Examples" @@ -790,6 +853,10 @@ msgid "" "alarm before opening the file; if the operation takes too long, the alarm " "signal will be sent, and the handler raises an exception. ::" msgstr "" +"這是一個最小範例程式。它使用 :func:`alarm` 函式來限制等待開啟檔案的時間;如果" +"檔案是用於可能未開啟的序列裝置,這會很有用,因為這通常會導致 :func:`os.open` " +"無限期地被擱置。解決方法是在開啟檔案前設定一個 5 秒的警報;如果操作時間過長," +"警報訊號就會被送出,而處理程式會產生例外。 ::" #: ../../library/signal.rst:690 msgid "" @@ -809,10 +876,25 @@ msgid "" "\n" "signal.alarm(0) # Disable the alarm" msgstr "" +"import signal, os\n" +"\n" +"def handler(signum, frame):\n" +" signame = signal.Signals(signum).name\n" +" print(f'Signal handler called with signal {signame} ({signum})')\n" +" raise OSError(\"Couldn't open device!\")\n" +"\n" +"# 設定訊號處理程式與五秒警報\n" +"signal.signal(signal.SIGALRM, handler)\n" +"signal.alarm(5)\n" +"\n" +"# 這個 open() 可能無限期地被擱置\n" +"fd = os.open('/dev/ttyS0', os.O_RDWR)\n" +"\n" +"signal.alarm(0) # 停用警報" #: ../../library/signal.rst:707 msgid "Note on SIGPIPE" -msgstr "" +msgstr "關於 SIGPIPE 的說明" #: ../../library/signal.rst:709 msgid "" @@ -822,6 +904,10 @@ msgid "" "`BrokenPipeError: [Errno 32] Broken pipe`. To handle this case, wrap your " "entry point to catch this exception as follows::" msgstr "" +"將程式的輸出管道化到 :manpage:`head(1)` 之類的工具,會在你的行程的標準輸出接" +"收器提早關閉時,導致 :const:`SIGPIPE` 訊號傳送給你的行程。這會導致類似 :code:" +"`BrokenPipeError: [Errno 32] Broken pipe` 的例外。要處理這種情況,請將你的進" +"入點包裝成如下的樣子來捕捉這個例外: ::" #: ../../library/signal.rst:715 msgid "" @@ -847,6 +933,26 @@ msgid "" "if __name__ == '__main__':\n" " main()" msgstr "" +"import os\n" +"import sys\n" +"\n" +"def main():\n" +" try:\n" +" # 模擬大量輸出(你的程式取代此迴圈)\n" +" for x in range(10000):\n" +" print(\"y\")\n" +" # 在這裡清除輸出以強制 SIGPIPE 在這個 try 區塊\n" +" # 中被觸發\n" +" sys.stdout.flush()\n" +" except BrokenPipeError:\n" +" # Python 在退出時清除標準串流;為剩下的輸出重新導向\n" +" # 至 devnull 來避免關閉時的 BrokenPipeError\n" +" devnull = os.open(os.devnull, os.O_WRONLY)\n" +" os.dup2(devnull, sys.stdout.fileno())\n" +" sys.exit(1) # Python 在 EPIPE 時以錯誤碼 1 退出\n" +"\n" +"if __name__ == '__main__':\n" +" main()" #: ../../library/signal.rst:736 msgid "" @@ -855,10 +961,13 @@ msgid "" "unexpectedly whenever any socket connection is interrupted while your " "program is still writing to it." msgstr "" +"不要為了避免 :exc:`BrokenPipeError` 而將 :const:`SIGPIPE` 之處置 " +"(disposition) 設定為 :const:`SIG_DFL`。這樣做會導致你的程式在寫入任何 socket " +"連線時被中斷而意外退出。" #: ../../library/signal.rst:745 msgid "Note on Signal Handlers and Exceptions" -msgstr "" +msgstr "訊號處理程式與例外的說明" #: ../../library/signal.rst:747 msgid "" @@ -870,10 +979,15 @@ msgid "" "exception resulting from a signal handler) may on rare occasions put the " "program in an unexpected state." msgstr "" +"如果訊號處理程式產生例外,例外會傳送到主執行緒並可能在任何 :term:`bytecode` " +"指令之後發生。最值得注意的是,:exc:`KeyboardInterrupt` 可能在執行過程中的任何" +"時候出現。大多數 Python 程式碼,包括標準函式庫,都無法避免這種情況,因此 :" +"exc:`KeyboardInterrupt`\\ (或任何其他由訊號處理程式產生的例外)可能會在罕見" +"的情況下使程式處於預期之外的狀態。" #: ../../library/signal.rst:754 msgid "To illustrate this issue, consider the following code::" -msgstr "" +msgstr "為了說明這個問題,請參考以下程式碼: ::" #: ../../library/signal.rst:756 msgid "" @@ -892,6 +1006,20 @@ msgid "" " ...\n" " self.lock.release()" msgstr "" +"class SpamContext:\n" +" def __init__(self):\n" +" self.lock = threading.Lock()\n" +"\n" +" def __enter__(self):\n" +" # 如果 KeyboardInterrupt 在此發生則一切正常\n" +" self.lock.acquire()\n" +" # 如果 KeyboardInterrupt 在此發生,__exit__ 將不會被呼叫\n" +" ...\n" +" # KeyboardInterrupt 可能在函式回傳之前發生\n" +"\n" +" def __exit__(self, exc_type, exc_val, exc_tb):\n" +" ...\n" +" self.lock.release()" #: ../../library/signal.rst:771 msgid "" @@ -903,6 +1031,12 @@ msgid "" "own :const:`SIGINT` handler. Below is an example of an HTTP server that " "avoids :exc:`KeyboardInterrupt`::" msgstr "" +"對許多程式來說,尤其是那些只想在 :exc:`KeyboardInterrupt` 時退出的程式,這並" +"不是問題,但是對於複雜或需要高可靠性的應用程式來說,應該避免從訊號處理程式產" +"生例外。它們也應該避免將捕獲 :exc:`KeyboardInterrupt` 作為一種優雅關閉 " +"(gracefully shutting down) 的方式。相反地,它們應該安裝自己的 :const:" +"`SIGINT` 處理程式。以下是 HTTP 伺服器避免 :exc:`KeyboardInterrupt` 的範" +"例: ::" #: ../../library/signal.rst:779 msgid "" @@ -936,3 +1070,32 @@ msgid "" "serve_forever(httpd)\n" "print(\"Shutdown...\")" msgstr "" +"import signal\n" +"import socket\n" +"from selectors import DefaultSelector, EVENT_READ\n" +"from http.server import HTTPServer, SimpleHTTPRequestHandler\n" +"\n" +"interrupt_read, interrupt_write = socket.socketpair()\n" +"\n" +"def handler(signum, frame):\n" +" print('Signal handler called with signal', signum)\n" +" interrupt_write.send(b'\\0')\n" +"signal.signal(signal.SIGINT, handler)\n" +"\n" +"def serve_forever(httpd):\n" +" sel = DefaultSelector()\n" +" sel.register(interrupt_read, EVENT_READ)\n" +" sel.register(httpd, EVENT_READ)\n" +"\n" +" while True:\n" +" for key, _ in sel.select():\n" +" if key.fileobj == interrupt_read:\n" +" interrupt_read.recv(1)\n" +" return\n" +" if key.fileobj == httpd:\n" +" httpd.handle_request()\n" +"\n" +"print(\"Serving on port 8000\")\n" +"httpd = HTTPServer(('', 8000), SimpleHTTPRequestHandler)\n" +"serve_forever(httpd)\n" +"print(\"Shutdown...\")"