Skip to content

refactor: Update Client.run to have a better async I/O usage#2645

Open
DA-344 wants to merge 79 commits intoPycord-Development:masterfrom
DA-344:fix/client-run
Open

refactor: Update Client.run to have a better async I/O usage#2645
DA-344 wants to merge 79 commits intoPycord-Development:masterfrom
DA-344:fix/client-run

Conversation

@DA-344
Copy link
Contributor

@DA-344 DA-344 commented Nov 11, 2024

Summary

This PR refactors the Client.run logic to fix problems involving asyncio due to how the library used the loop:

Needs testing

Exception
  File "/home/container/main.py", line 23, in <module>
    bot.run(BOT_TOKEN)

  File "/home/container/.local/lib/python3.11/site-packages/discord/client.py", line 772, in run
    loop.run_forever()

  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 608, in run_forever
    self._run_once()

  File "/usr/local/lib/python3.11/asyncio/base_events.py", line 1936, in _run_once
    handle._run()

  File "/usr/local/lib/python3.11/asyncio/events.py", line 84, in _run
    self._context.run(self._callback, *self._args)

  File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 956, in _read_ready
    self._read_ready_cb()

  File "/usr/local/lib/python3.11/asyncio/selector_events.py", line 988, in _read_ready__get_buffer
    self._protocol.buffer_updated(nbytes)

  File "/usr/local/lib/python3.11/asyncio/sslproto.py", line 439, in buffer_updated
    self._do_handshake()

  File "/usr/local/lib/python3.11/asyncio/sslproto.py", line 560, in _do_handshake
    self._sslobj.do_handshake()

  File "/usr/local/lib/python3.11/ssl.py", line 979, in do_handshake
    self._sslobj.do_handshake()

Information

  • This PR fixes an issue.
  • This PR adds something new (e.g. new method or parameters).
  • This PR is a breaking change (e.g. methods or parameters removed/renamed).
  • This PR is not a code change (e.g. documentation, README, typehinting,
    examples, ...).

Checklist

  • I have searched the open pull requests for duplicates.
  • If code changes were made then they have been tested.
    • I have updated the documentation to reflect the changes.
  • If type: ignore comments were used, a comment is also left explaining why.
  • I have updated the changelog to include these changes.

@Lulalaby Lulalaby requested review from Dorukyum, NeloBlivion and plun1331 and removed request for ChickenDevs November 11, 2024 23:03
DA-344 and others added 2 commits November 19, 2024 08:23
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
Signed-off-by: DA344 <108473820+DA-344@users.noreply.github.com>
Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com>
Signed-off-by: DA344 <108473820+DA-344@users.noreply.github.com>
@DA-344
Copy link
Contributor Author

DA-344 commented Nov 19, 2024

Applied all the changes Dorukyum requested.

Before merging, I would like some feedback on this discussion message

@Lulalaby Lulalaby added this to the v2.8 milestone Dec 24, 2025
@Lulalaby Lulalaby removed the on hold label Dec 24, 2025
@Paillat-dev Paillat-dev added priority: high High Priority and removed priority: medium Medium Priority labels Dec 26, 2025
@Paillat-dev
Copy link
Member

@Lumabots When able can you run this for like 24h with some bot ?

([#2905](https://github.com/Pycord-Development/pycord/pull/2905))
- `view=None` in various methods causing an AttributeError.
([#2915](https://github.com/Pycord-Development/pycord/pull/2915))
- Fixed Async I/O errors that could be raised when using `Client.run`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably should be more extensive.

)


def is_ambiguous(dt: datetime.datetime) -> bool:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this is doing here. Is it required ? Or is it an additional feature ? In any case it should at least be in the changelog and maybe a separate PR depending on what the others think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is used internally on Loop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but it wasn't present before. Does it change / increase the types of accepted inputs for loops ?

Copy link
Contributor Author

@DA-344 DA-344 Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this checks whether a datetime object falls in a ambiguous local time by DST transition (eg Spanish winter & summer local times)

so there is a moment in which the clock is set back and the same local hour occurs twice (that is why it uses fold)

this checks whether the datetime already has timezone data (dt.tzinfo) or uses a utc or fixed-offset datetime.timezone instance.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the unrelated datetime changes and (if you want) move them to a separate pull request, I feel like this PR is already heavy enough

Copy link
Member

@plun1331 plun1331 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it refactors a large amount of ext.tasks, much of it unrelated to asyncio usage. That should be in a different pull request.

loop: asyncio.AbstractEventLoop | None = None,
name: str | None = MISSING,
overlap: bool | int = False,
create_loop: bool = False,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically makes this breaking I believe. True default probably wouldn't be most ideal though?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it wouldn't be breaking as long as Client.start is called.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it is breaking

return task

def dispatch(self, event: str, *args: Any, **kwargs: Any) -> None:
_log.debug("Dispatching event %s", event)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

**options: Any,
) -> None:
self.loop: asyncio.AbstractEventLoop = loop
self.loop: asyncio.AbstractEventLoop = loop or MISSING
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a difference between using None and MISSING here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no difference here tbh, but it is done to prevent assert state.loop is not None everytime state.loop is accessed.

@Paillat-dev
Copy link
Member

Could you take a look at #2873 (comment) ?

@Paillat-dev Paillat-dev modified the milestones: v2.8.0rc.1, next-major Mar 15, 2026
@Lulalaby Lulalaby added this to Pycord Mar 18, 2026
@github-project-automation github-project-automation bot moved this to Todo in Pycord Mar 18, 2026
@Paillat-dev Paillat-dev self-requested a review March 21, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hold: testing This pull request requires further testing priority: high High Priority

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Event loop stalls even with an idle bot

9 participants