prompt-toolkit / prompt-toolkit/python-prompt-toolkit

RuntimeError: This event loop is already running

Open
#1,824 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
10.6k
Forks
815
PR merge metrics
No merged PRs in 30d

Description

Using prompt-toolkit 3.0.41, every time I launch scrapy shell (Scrapy 2.11.0) with ipython 8.18.0 and Python 3.10.12, the following stacktrace is produced:


RuntimeError Traceback (most recent call last)
File ~/.local/bin/scrapy:8
6 if name == 'main':
7 sys.argv[0] = re.sub(r'(-script.pyw|.exe)?$', '', sys.argv[0])
----> 8 sys.exit(execute())

File ~/.local/lib/python3.10/site-packages/scrapy/cmdline.py:161, in execute(argv, settings)
158 _run_print_help(parser, cmd.process_options, args, opts)
160 cmd.crawler_process = CrawlerProcess(settings)
--> 161 _run_print_help(parser, _run_command, cmd, args, opts)
162 sys.exit(cmd.exitcode)

File ~/.local/lib/python3.10/site-packages/scrapy/cmdline.py:114, in _run_print_help(parser, func, *a, **kw)
112 def _run_print_help(parser, func, *a, **kw):
113 try:
--> 114 func(*a, **kw)
115 except UsageError as e:
116 if str(e):

File ~/.local/lib/python3.10/site-packages/scrapy/cmdline.py:169, in _run_command(cmd, args, opts)
167 _run_command_profiled(cmd, args, opts)
168 else:
--> 169 cmd.run(args, opts)

File ~/.local/lib/python3.10/site-packages/scrapy/commands/shell.py:88, in Command.run(self, args, opts)
85 self._start_crawler_thread()
87 shell = Shell(crawler, update_vars=self.update_vars, code=opts.code)
---> 88 shell.start(url=url, redirect=not opts.no_redirect)

File ~/.local/lib/python3.10/site-packages/scrapy/shell.py:75, in Shell.start(self, url, request, response, spider, redirect)
73 # always add standard shell as fallback
74 shells += ["python"]
---> 75 start_python_console(
76 self.vars, shells=shells, banner=self.vars.pop("banner", "")
77 )

File ~/.local/lib/python3.10/site-packages/scrapy/utils/console.py:108, in start_python_console(namespace, banner, shells)
106 shell = get_shell_embed_func(shells)
107 if shell is not None:
--> 108 shell(namespace=namespace, banner=banner)
109 except SystemExit: # raised when using exit() in python code.interact
110 pass

File ~/.local/lib/python3.10/site-packages/scrapy/utils/console.py:24, in _embed_ipython_shell..wrapper(namespace, banner)
20 InteractiveShellEmbed.clear_instance()
21 shell = InteractiveShellEmbed.instance(
22 banner1=banner, user_ns=namespace, config=config
23 )
---> 24 shell()

File /usr/lib/python3.10/site-packages/IPython/terminal/embed.py:251, in InteractiveShellEmbed.call(self, header, local_ns, module, dummy, stack_depth, compile_flags, **kw)
247 self.show_banner()
249 # Call the embedding code with a stack depth of 1 so it can skip over
250 # our call and get the original caller's namespaces.
--> 251 self.mainloop(
252 local_ns, module, stack_depth=stack_depth, compile_flags=compile_flags
253 )
255 self.banner2 = self.old_banner2
257 if self.exit_msg is not None:

File /usr/lib/python3.10/site-packages/IPython/terminal/embed.py:343, in InteractiveShellEmbed.mainloop(self, local_ns, module, stack_depth, compile_flags)
340 self.set_completer_frame()
342 with self.builtin_trap, self.display_trap:
--> 343 self.interact()
345 # now, purge out the local namespace of IPython's hidden variables.
346 if local_ns is not None:

File /usr/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py:872, in TerminalInteractiveShell.interact(self)
869 print(self.separate_in, end='')
871 try:
--> 872 code = self.prompt_for_code()
873 except EOFError:
874 if (not self.confirm_exit)
875 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):

File /usr/lib/python3.10/site-packages/IPython/terminal/interactiveshell.py:813, in TerminalInteractiveShell.prompt_for_code(self)
807 text = asyncio_loop.run_until_complete(
808 self.pt_app.prompt_async(
809 default=default, **self._extra_prompt_options()
810 )
811 )
812 else:
--> 813 text = self.pt_app.prompt(
814 default=default,
815 inputhook=self._inputhook,
816 **self._extra_prompt_options(),
817 )
819 return text

File ~/.local/lib/python3.10/site-packages/prompt_toolkit/shortcuts/prompt.py:1026, in PromptSession.prompt(self, message, editing_mode, refresh_interval, vi_mode, lexer, completer, complete_in_thread, is_password, key_bindings, bottom_toolbar, style, color_depth, cursor, include_default_pygments_style, style_transformation, swap_light_and_dark_colors, rprompt, multiline, prompt_continuation, wrap_lines, enable_history_search, search_ignore_case, complete_while_typing, validate_while_typing, complete_style, auto_suggest, validator, clipboard, mouse_support, input_processors, placeholder, reserve_space_for_menu, enable_system_prompt, enable_suspend, enable_open_in_editor, tempfile_suffix, tempfile, default, accept_default, pre_run, set_exception_handler, handle_sigint, in_thread, inputhook)
1023 with self._dumb_prompt(self.message) as dump_app:
1024 return dump_app.run(in_thread=in_thread, handle_sigint=handle_sigint)
-> 1026 return self.app.run(
1027 set_exception_handler=set_exception_handler,
1028 in_thread=in_thread,
1029 handle_sigint=handle_sigint,
1030 inputhook=inputhook,
1031 )

File ~/.local/lib/python3.10/site-packages/prompt_toolkit/application/application.py:994, in Application.run(self, pre_run, set_exception_handler, handle_sigint, in_thread, inputhook)
991 return asyncio.run(coro)
992 else:
993 # Use existing loop.
--> 994 return loop.run_until_complete(coro)
996 else:
997 # No loop installed. Run like usual.
998 return asyncio.run(coro)

File /usr/lib64/python3.10/asyncio/base_events.py:625, in BaseEventLoop.run_until_complete(self, future)
614 """Run until the Future is done.
615
616 If the argument is a coroutine, it is wrapped in a Task.
(...)
622 Return the Future's result, or raise its exception.
623 """
624 self._check_closed()
--> 625 self._check_running()
627 new_task = not futures.isfuture(future)
628 future = tasks.ensure_future(future, loop=self)

File /usr/lib64/python3.10/asyncio/base_events.py:584, in BaseEventLoop._check_running(self)
582 def _check_running(self):
583 if self.is_running():
--> 584 raise RuntimeError('This event loop is already running')
585 if events._get_running_loop() is not None:
586 raise RuntimeError(
587 'Cannot run the event loop while another loop is running')

RuntimeError: This event loop is already running

The cause seems to be using asyncio.get_event_loop(), which will soon be deprecated. This is related to https://github.com/scrapy/scrapy/issues/6160.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with prompt_toolkit/application/application.py, where the stack trace calls the existing asyncio event loop and raises RuntimeError. Reproduce the failure with prompt-toolkit 3.0.41, Scrapy 2.11.0, IPython 8.18.0, and Python 3.10.12, then inspect the related Scrapy issue. Done means the reported scrapy shell launch no longer produces this event-loop error.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.