diff --git a/scrapy/core/engine.py b/scrapy/core/engine.py index 0631f7feb..be76ad8c3 100644 --- a/scrapy/core/engine.py +++ b/scrapy/core/engine.py @@ -141,6 +141,9 @@ class ExecutionEngine: raise RuntimeError("Engine already running") self.start_time = time() await self.signals.send_catch_log_async(signal=signals.engine_started) + if _start_request_processing and self.spider is None: + # require an opened spider when not run in scrapy shell + return self.running = True self._closewait = Deferred() if _start_request_processing: @@ -543,5 +546,6 @@ class ExecutionEngine: dfd.addErrback(log_failure("Error while unassigning spider")) dfd.addBoth(lambda _: self._spider_closed_callback(spider)) + dfd.addErrback(log_failure("Error running spider_closed_callback")) return dfd diff --git a/tests/test_engine.py b/tests/test_engine.py index d9d25c240..9a3075f31 100644 --- a/tests/test_engine.py +++ b/tests/test_engine.py @@ -507,7 +507,9 @@ class TestEngine(TestEngineBase): finally: timer.cancel() - assert b"Traceback" not in stderr, stderr + stderr_str = stderr.decode("utf-8") + assert "AttributeError" not in stderr_str, stderr_str + assert "AssertionError" not in stderr_str, stderr_str def test_request_scheduled_signal(caplog): diff --git a/tests/test_engine_loop.py b/tests/test_engine_loop.py index 4e82ad4ba..d4c7b8698 100644 --- a/tests/test_engine_loop.py +++ b/tests/test_engine_loop.py @@ -112,7 +112,8 @@ class TestMain(TestCase): with LogCapture(level=ERROR) as log: await maybe_deferred_to_future(crawler.crawl()) - assert not log.records + assert len(log.records) == 1 + assert log.records[0].msg == "Error running spider_closed_callback" finish_reason = crawler.stats.get_value("finish_reason") assert finish_reason == "shutdown", f"{finish_reason=}" expected_urls = []