如何在Windows 11中以asyncio模式运行ptpython?
Windows 11下ptpython asyncio REPL无法正常工作的解决方法
问题背景
在Windows 11上使用Python 3.12.3(Python 3.8.10测试也存在相同问题)时,系统内置的asyncio REPL可以正常运行:
PS C:\> python -m asyncio asyncio REPL 3.12.3 (tags/v3.12.3:f6650f9, Apr 9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)] on win32 Use "await" directly instead of "asyncio.run()". Type "help", "copyright", "credits" or "license" for more information. >>> import asyncio >>> await asyncio.sleep(1, 'Done!') 'Done!' >>> exit()
但通过ptpython --asyncio启动异步REPL后,执行await语句会抛出NotImplementedError和NameError:
C:\> ptpython --asyncio Starting ptpython asyncio REPL Use "await" directly instead of "asyncio.run()". In [1]: await asyncio.sleep(1, 'Done!') Traceback (most recent call last): File "c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\repl.py", line 183, in run_and_show_expression_async loop.add_signal_handler(signal.SIGINT, lambda *_: task.cancel()) File "c:\users\james\appdata\local\programs\python\python38-32\lib\asyncio\events.py", line 536, in add_signal_handler raise NotImplementedError NotImplementedError Traceback (most recent call last): File "c:\users\james\appdata\local\programs\python\python38-32\lib\runpy.py", line 194, in _run_module_as_main return _run_code(code, main_globals, None, File "c:\users\james\appdata\local\programs\python\python38-32\lib\runpy.py", line 87, in _run_code exec(code, run_globals) File "C:\users\james\appdata\local\Programs\Python\Python38-32\Scripts\ptpython.exe\__main__.py", line 7, in <module> File "c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\entry_points\run_ptpython.py", line 231, in run asyncio.run(embed_result) File "c:\users\james\appdata\local\programs\python\python38-32\lib\asyncio\runners.py", line 44, in run return loop.run_until_complete(main) File "c:\users\james\appdata\local\programs\python\python38-32\lib\asyncio\base_events.py", line 616, in run_until_complete return future.result() File "c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\repl.py", line 528, in coroutine await repl.run_async() File "c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\repl.py", line 252, in run_async await self.run_and_show_expression_async(text) File "c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\repl.py", line 206, in run_and_show_expression_async loop.remove_signal_handler(signal.SIGINT) File "c:\users\james\appdata\local\programs\python\python38-32\lib\asyncio\events.py", line 539, in remove_signal_handler raise NotImplementedError NotImplementedError Task exception was never retrieved future: <Task finished name='Task-61' coro=<PythonRepl.run_and_show_expression_async.<locals>.eval() done, defined at c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\repl.py:172> exception=NameError("name 'asyncio' is not defined")> Traceback (most recent call last): File "c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\repl.py", line 175, in eval return await self.eval_async(text) File "c:\users\james\appdata\local\programs\python\python38-32\lib\site-packages\ptpython\repl.py", line 329, in eval_async result = await result File "<stdin>", line 1, in <module> NameError: name 'asyncio' is not defined
现有临时解决方法(来自@jupiterbjy):
PS C:\> ptpython >>> import asyncio >>> async def main(): ... return await asyncio.sleep(1, 'Done!') ... >>> print(asyncio.run(main())) Done! >>> exit()
错误原因
- NotImplementedError:Windows系统不支持asyncio的
add_signal_handler和remove_signal_handler方法(这两个方法是Unix平台专属),但ptpython的asyncio REPL代码未做平台兼容判断,直接调用导致报错。 - NameError:由于上述报错中断了初始化流程,asyncio模块未被自动导入,而系统内置REPL会自动完成asyncio的导入。
解决方法
方法1:修改ptpython源码添加平台兼容
找到ptpython安装目录下的repl.py(路径示例:C:\Users\<你的用户名>\AppData\Local\Programs\Python\Python3x\Lib\site-packages\ptpython\repl.py),定位到run_and_show_expression_async函数,添加平台判断跳过Windows不支持的信号处理逻辑:
# 在文件顶部导入sys模块(如果没有的话) import sys import signal import asyncio # ... async def run_and_show_expression_async(self, text: str) -> None: # ... 保留原有代码 ... loop = asyncio.get_running_loop() # 新增:仅在非Windows平台添加信号处理 if sys.platform != 'win32': loop.add_signal_handler(signal.SIGINT, lambda *_: task.cancel()) try: result = await task except asyncio.CancelledError: self._handle_keyboard_interrupt() return finally: # 新增:仅在非Windows平台移除信号处理 if sys.platform != 'win32': loop.remove_signal_handler(signal.SIGINT) # ... 保留原有代码 ...
方法2:通过ptpython配置文件实现兼容
创建ptpython配置文件(Windows路径:C:\Users\<你的用户名>\.ptpython\config.py,如果目录不存在则手动创建),添加以下内容:
import asyncio import sys import signal from ptpython.repl import PythonRepl def configure(repl: PythonRepl) -> None: # 自动导入asyncio,避免NameError repl.auto_imports.add('asyncio') # 重写异步执行方法,跳过Windows信号处理 original_run = repl.run_and_show_expression_async async def patched_run(text: str) -> None: loop = asyncio.get_running_loop() original_handler = None # 仅在非Windows平台处理信号 if sys.platform != 'win32': try: original_handler = loop.get_signal_handler(signal.SIGINT) loop.add_signal_handler(signal.SIGINT, lambda *_: asyncio.current_task().cancel()) except Exception: pass try: await original_run(text) finally: # 恢复原有信号处理(如果存在) if sys.platform != 'win32' and original_handler is not None: loop.add_signal_handler(signal.SIGINT, original_handler) elif sys.platform != 'win32': loop.remove_signal_handler(signal.SIGINT) repl.run_and_show_expression_async = patched_run
之后运行ptpython --asyncio即可正常使用await语句。
方法3:升级ptpython到最新版本
尝试升级ptpython,检查官方是否已修复Windows平台的兼容问题:
pip install --upgrade ptpython
内容的提问来源于stack exchange,提问作者James S.
相关产品推荐
相关产品推荐

