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 passFile ~/.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 textFile ~/.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 scrapy/scrapy#6160.