|
1 | 1 | # SOME DESCRIPTIVE TITLE. |
2 | | -# Copyright (C) 2001-2025, Python Software Foundation |
| 2 | +# Copyright (C) 2001-2026, Python Software Foundation |
3 | 3 | # This file is distributed under the same license as the Python package. |
4 | 4 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
5 | 5 | # |
6 | 6 | # Translators: |
7 | | -# python-doc bot, 2025 |
| 7 | +# python-doc bot, 2026 |
8 | 8 | # |
9 | 9 | #, fuzzy |
10 | 10 | msgid "" |
11 | 11 | msgstr "" |
12 | 12 | "Project-Id-Version: Python 3.13\n" |
13 | 13 | "Report-Msgid-Bugs-To: \n" |
14 | | -"POT-Creation-Date: 2025-05-23 14:55+0000\n" |
| 14 | +"POT-Creation-Date: 2026-03-21 15:06+0000\n" |
15 | 15 | "PO-Revision-Date: 2025-09-15 01:03+0000\n" |
16 | | -"Last-Translator: python-doc bot, 2025\n" |
| 16 | +"Last-Translator: python-doc bot, 2026\n" |
17 | 17 | "Language-Team: Russian (https://app.transifex.com/python-doc/teams/5390/ru/)\n" |
18 | 18 | "MIME-Version: 1.0\n" |
19 | 19 | "Content-Type: text/plain; charset=UTF-8\n" |
@@ -262,6 +262,7 @@ msgid "" |
262 | 262 | msgstr "" |
263 | 263 |
|
264 | 264 | #: ../../library/asyncio-dev.rst:172 ../../library/asyncio-dev.rst:217 |
| 265 | +#: ../../library/asyncio-dev.rst:391 ../../library/asyncio-dev.rst:448 |
265 | 266 | msgid "Output::" |
266 | 267 | msgstr "" |
267 | 268 |
|
@@ -369,3 +370,292 @@ msgid "" |
369 | 370 | " raise Exception(\"not consumed\")\n" |
370 | 371 | "Exception: not consumed" |
371 | 372 | msgstr "" |
| 373 | + |
| 374 | +#: ../../library/asyncio-dev.rst:252 |
| 375 | +msgid "Asynchronous generators best practices" |
| 376 | +msgstr "" |
| 377 | + |
| 378 | +#: ../../library/asyncio-dev.rst:254 |
| 379 | +msgid "" |
| 380 | +"Writing correct and efficient asyncio code requires awareness of certain " |
| 381 | +"pitfalls. This section outlines essential best practices that can save you " |
| 382 | +"hours of debugging." |
| 383 | +msgstr "" |
| 384 | + |
| 385 | +#: ../../library/asyncio-dev.rst:259 |
| 386 | +msgid "Close asynchronous generators explicitly" |
| 387 | +msgstr "" |
| 388 | + |
| 389 | +#: ../../library/asyncio-dev.rst:261 |
| 390 | +msgid "" |
| 391 | +"It is recommended to manually close the :term:`asynchronous generator " |
| 392 | +"<asynchronous generator iterator>`. If a generator exits early - for " |
| 393 | +"example, due to an exception raised in the body of an ``async for`` loop - " |
| 394 | +"its asynchronous cleanup code may run in an unexpected context. This can " |
| 395 | +"occur after the tasks it depends on have completed, or during the event loop" |
| 396 | +" shutdown when the async-generator's garbage collection hook is called." |
| 397 | +msgstr "" |
| 398 | + |
| 399 | +#: ../../library/asyncio-dev.rst:269 |
| 400 | +msgid "" |
| 401 | +"To avoid this, explicitly close the generator by calling its " |
| 402 | +":meth:`~agen.aclose` method, or use the :func:`contextlib.aclosing` context " |
| 403 | +"manager::" |
| 404 | +msgstr "" |
| 405 | + |
| 406 | +#: ../../library/asyncio-dev.rst:273 |
| 407 | +msgid "" |
| 408 | +"import asyncio\n" |
| 409 | +"import contextlib\n" |
| 410 | +"\n" |
| 411 | +"async def gen():\n" |
| 412 | +" yield 1\n" |
| 413 | +" yield 2\n" |
| 414 | +"\n" |
| 415 | +"async def func():\n" |
| 416 | +" async with contextlib.aclosing(gen()) as g:\n" |
| 417 | +" async for x in g:\n" |
| 418 | +" break # Don't iterate until the end\n" |
| 419 | +"\n" |
| 420 | +"asyncio.run(func())" |
| 421 | +msgstr "" |
| 422 | + |
| 423 | +#: ../../library/asyncio-dev.rst:287 |
| 424 | +msgid "" |
| 425 | +"As noted above, the cleanup code for these asynchronous generators is " |
| 426 | +"deferred. The following example demonstrates that the finalization of an " |
| 427 | +"asynchronous generator can occur in an unexpected order::" |
| 428 | +msgstr "" |
| 429 | + |
| 430 | +#: ../../library/asyncio-dev.rst:291 |
| 431 | +msgid "" |
| 432 | +"import asyncio\n" |
| 433 | +"work_done = False\n" |
| 434 | +"\n" |
| 435 | +"async def cursor():\n" |
| 436 | +" try:\n" |
| 437 | +" yield 1\n" |
| 438 | +" finally:\n" |
| 439 | +" assert work_done\n" |
| 440 | +"\n" |
| 441 | +"async def rows():\n" |
| 442 | +" global work_done\n" |
| 443 | +" try:\n" |
| 444 | +" yield 2\n" |
| 445 | +" finally:\n" |
| 446 | +" await asyncio.sleep(0.1) # immitate some async work\n" |
| 447 | +" work_done = True\n" |
| 448 | +"\n" |
| 449 | +"\n" |
| 450 | +"async def main():\n" |
| 451 | +" async for c in cursor():\n" |
| 452 | +" async for r in rows():\n" |
| 453 | +" break\n" |
| 454 | +" break\n" |
| 455 | +"\n" |
| 456 | +"asyncio.run(main())" |
| 457 | +msgstr "" |
| 458 | + |
| 459 | +#: ../../library/asyncio-dev.rst:317 |
| 460 | +msgid "For this example, we get the following output::" |
| 461 | +msgstr "" |
| 462 | + |
| 463 | +#: ../../library/asyncio-dev.rst:319 |
| 464 | +msgid "" |
| 465 | +"unhandled exception during asyncio.run() shutdown\n" |
| 466 | +"task: <Task finished name='Task-3' coro=<<async_generator_athrow without __name__>()> exception=AssertionError()>\n" |
| 467 | +"Traceback (most recent call last):\n" |
| 468 | +" File \"example.py\", line 6, in cursor\n" |
| 469 | +" yield 1\n" |
| 470 | +"asyncio.exceptions.CancelledError\n" |
| 471 | +"\n" |
| 472 | +"During handling of the above exception, another exception occurred:\n" |
| 473 | +"\n" |
| 474 | +"Traceback (most recent call last):\n" |
| 475 | +" File \"example.py\", line 8, in cursor\n" |
| 476 | +" assert work_done\n" |
| 477 | +" ^^^^^^^^^\n" |
| 478 | +"AssertionError" |
| 479 | +msgstr "" |
| 480 | + |
| 481 | +#: ../../library/asyncio-dev.rst:334 |
| 482 | +msgid "" |
| 483 | +"The ``cursor()`` asynchronous generator was finalized before the ``rows`` " |
| 484 | +"generator - an unexpected behavior." |
| 485 | +msgstr "" |
| 486 | + |
| 487 | +#: ../../library/asyncio-dev.rst:337 |
| 488 | +msgid "" |
| 489 | +"The example can be fixed by explicitly closing the ``cursor`` and ``rows`` " |
| 490 | +"async-generators::" |
| 491 | +msgstr "" |
| 492 | + |
| 493 | +#: ../../library/asyncio-dev.rst:340 |
| 494 | +msgid "" |
| 495 | +"async def main():\n" |
| 496 | +" async with contextlib.aclosing(cursor()) as cursor_gen:\n" |
| 497 | +" async for c in cursor_gen:\n" |
| 498 | +" async with contextlib.aclosing(rows()) as rows_gen:\n" |
| 499 | +" async for r in rows_gen:\n" |
| 500 | +" break\n" |
| 501 | +" break" |
| 502 | +msgstr "" |
| 503 | + |
| 504 | +#: ../../library/asyncio-dev.rst:350 |
| 505 | +msgid "Create asynchronous generators only when the event loop is running" |
| 506 | +msgstr "" |
| 507 | + |
| 508 | +#: ../../library/asyncio-dev.rst:352 |
| 509 | +msgid "" |
| 510 | +"It is recommended to create :term:`asynchronous generators <asynchronous " |
| 511 | +"generator iterator>` only after the event loop has been created." |
| 512 | +msgstr "" |
| 513 | + |
| 514 | +#: ../../library/asyncio-dev.rst:356 |
| 515 | +msgid "" |
| 516 | +"To ensure that asynchronous generators close reliably, the event loop uses " |
| 517 | +"the :func:`sys.set_asyncgen_hooks` function to register callback functions. " |
| 518 | +"These callbacks update the list of running asynchronous generators to keep " |
| 519 | +"it in a consistent state." |
| 520 | +msgstr "" |
| 521 | + |
| 522 | +#: ../../library/asyncio-dev.rst:361 |
| 523 | +msgid "" |
| 524 | +"When the :meth:`loop.shutdown_asyncgens() <asyncio.loop.shutdown_asyncgens>`" |
| 525 | +" function is called, the running generators are stopped gracefully and the " |
| 526 | +"list is cleared." |
| 527 | +msgstr "" |
| 528 | + |
| 529 | +#: ../../library/asyncio-dev.rst:365 |
| 530 | +msgid "" |
| 531 | +"The asynchronous generator invokes the corresponding system hook during its " |
| 532 | +"first iteration. At the same time, the generator records that the hook has " |
| 533 | +"been called and does not call it again." |
| 534 | +msgstr "" |
| 535 | + |
| 536 | +#: ../../library/asyncio-dev.rst:369 |
| 537 | +msgid "" |
| 538 | +"Therefore, if iteration begins before the event loop is created, the event " |
| 539 | +"loop will not be able to add the generator to its list of active generators " |
| 540 | +"because the hooks are set after the generator attempts to call them. " |
| 541 | +"Consequently, the event loop will not be able to terminate the generator if " |
| 542 | +"necessary." |
| 543 | +msgstr "" |
| 544 | + |
| 545 | +#: ../../library/asyncio-dev.rst:375 |
| 546 | +msgid "Consider the following example::" |
| 547 | +msgstr "" |
| 548 | + |
| 549 | +#: ../../library/asyncio-dev.rst:377 |
| 550 | +msgid "" |
| 551 | +"import asyncio\n" |
| 552 | +"\n" |
| 553 | +"async def agenfn():\n" |
| 554 | +" try:\n" |
| 555 | +" yield 10\n" |
| 556 | +" finally:\n" |
| 557 | +" await asyncio.sleep(0)\n" |
| 558 | +"\n" |
| 559 | +"\n" |
| 560 | +"with asyncio.Runner() as runner:\n" |
| 561 | +" agen = agenfn()\n" |
| 562 | +" print(runner.run(anext(agen)))\n" |
| 563 | +" del agen" |
| 564 | +msgstr "" |
| 565 | + |
| 566 | +#: ../../library/asyncio-dev.rst:393 |
| 567 | +msgid "" |
| 568 | +"10\n" |
| 569 | +"Exception ignored while closing generator <async_generator object agenfn at 0x000002F71CD10D70>:\n" |
| 570 | +"Traceback (most recent call last):\n" |
| 571 | +" File \"example.py\", line 13, in <module>\n" |
| 572 | +" del agen\n" |
| 573 | +" ^^^^\n" |
| 574 | +"RuntimeError: async generator ignored GeneratorExit" |
| 575 | +msgstr "" |
| 576 | + |
| 577 | +#: ../../library/asyncio-dev.rst:401 |
| 578 | +msgid "This example can be fixed as follows::" |
| 579 | +msgstr "" |
| 580 | + |
| 581 | +#: ../../library/asyncio-dev.rst:403 |
| 582 | +msgid "" |
| 583 | +"import asyncio\n" |
| 584 | +"\n" |
| 585 | +"async def agenfn():\n" |
| 586 | +" try:\n" |
| 587 | +" yield 10\n" |
| 588 | +" finally:\n" |
| 589 | +" await asyncio.sleep(0)\n" |
| 590 | +"\n" |
| 591 | +"async def main():\n" |
| 592 | +" agen = agenfn()\n" |
| 593 | +" print(await anext(agen))\n" |
| 594 | +" del agen\n" |
| 595 | +"\n" |
| 596 | +"asyncio.run(main())" |
| 597 | +msgstr "" |
| 598 | + |
| 599 | +#: ../../library/asyncio-dev.rst:420 |
| 600 | +msgid "Avoid concurrent iteration and closure of the same generator" |
| 601 | +msgstr "" |
| 602 | + |
| 603 | +#: ../../library/asyncio-dev.rst:422 |
| 604 | +msgid "" |
| 605 | +"Async generators may be reentered while another :meth:`~agen.__anext__` / " |
| 606 | +":meth:`~agen.athrow` / :meth:`~agen.aclose` call is in progress. This may " |
| 607 | +"lead to an inconsistent state of the async generator and can cause errors." |
| 608 | +msgstr "" |
| 609 | + |
| 610 | +#: ../../library/asyncio-dev.rst:427 |
| 611 | +msgid "Let's consider the following example::" |
| 612 | +msgstr "" |
| 613 | + |
| 614 | +#: ../../library/asyncio-dev.rst:429 |
| 615 | +msgid "" |
| 616 | +"import asyncio\n" |
| 617 | +"\n" |
| 618 | +"async def consumer():\n" |
| 619 | +" for idx in range(100):\n" |
| 620 | +" await asyncio.sleep(0)\n" |
| 621 | +" message = yield idx\n" |
| 622 | +" print('received', message)\n" |
| 623 | +"\n" |
| 624 | +"async def amain():\n" |
| 625 | +" agenerator = consumer()\n" |
| 626 | +" await agenerator.asend(None)\n" |
| 627 | +"\n" |
| 628 | +" fa = asyncio.create_task(agenerator.asend('A'))\n" |
| 629 | +" fb = asyncio.create_task(agenerator.asend('B'))\n" |
| 630 | +" await fa\n" |
| 631 | +" await fb\n" |
| 632 | +"\n" |
| 633 | +"asyncio.run(amain())" |
| 634 | +msgstr "" |
| 635 | + |
| 636 | +#: ../../library/asyncio-dev.rst:450 |
| 637 | +msgid "" |
| 638 | +"received A\n" |
| 639 | +"Traceback (most recent call last):\n" |
| 640 | +" File \"test.py\", line 38, in <module>\n" |
| 641 | +" asyncio.run(amain())\n" |
| 642 | +" ~~~~~~~~~~~^^^^^^^^^\n" |
| 643 | +" File \"Lib/asyncio/runners.py\", line 204, in run\n" |
| 644 | +" return runner.run(main)\n" |
| 645 | +" ~~~~~~~~~~^^^^^^\n" |
| 646 | +" File \"Lib/asyncio/runners.py\", line 127, in run\n" |
| 647 | +" return self._loop.run_until_complete(task)\n" |
| 648 | +" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^\n" |
| 649 | +" File \"Lib/asyncio/base_events.py\", line 719, in run_until_complete\n" |
| 650 | +" return future.result()\n" |
| 651 | +" ~~~~~~~~~~~~~^^\n" |
| 652 | +" File \"test.py\", line 36, in amain\n" |
| 653 | +" await fb\n" |
| 654 | +"RuntimeError: anext(): asynchronous generator is already running" |
| 655 | +msgstr "" |
| 656 | + |
| 657 | +#: ../../library/asyncio-dev.rst:469 |
| 658 | +msgid "" |
| 659 | +"Therefore, it is recommended to avoid using asynchronous generators in " |
| 660 | +"parallel tasks or across multiple event loops." |
| 661 | +msgstr "" |
0 commit comments