为什么从pywikibot调用scrapy spider会产生ReactorNotRestartable错误?

为什么从pywikibot调用scrapy spider会产生ReactorNotRestartable错误?,scrapy,reactor,pywikibot,Scrapy,Reactor,Pywikibot,我可以使用CrawlerRunner或CrawlerProcess从另一个Python脚本调用scrapy spider。但是,当我试图从pywikibot机器人调用同一个spider调用类时,我得到了一个ReactorNotRestartable错误。这是为什么?我如何修复它 以下是错误: 文件“\scripts\userscripts\ReplicationWiki\RWLoad.py”,第161行,格式为“新建”页面 aea=AEAMetadata(url=DOI_url) 文件“\scr

我可以使用CrawlerRunner或CrawlerProcess从另一个Python脚本调用scrapy spider。但是,当我试图从pywikibot机器人调用同一个spider调用类时,我得到了一个ReactorNotRestartable错误。这是为什么?我如何修复它

以下是错误:

文件“\scripts\userscripts\ReplicationWiki\RWLoad.py”,第161行,格式为“新建”页面
aea=AEAMetadata(url=DOI_url)
文件“\scripts\userscripts\ReplicationWiki\GetAEAMetadata.py”,第39行,在__
reactor.run()#脚本将在此阻塞,直到所有爬网作业完成
文件“C:\Users\lextr\.conda\envs\py37\lib\site packages\twisted\internet\base.py”,第1282行,正在运行
self.startRunning(installSignalHandlers=installSignalHandlers)
startRunning中的文件“C:\Users\lextr\.conda\envs\py37\lib\site packages\twisted\internet\base.py”,第1262行
反应器基础启动耳轴(自)
startRunning中的文件“C:\Users\lextr\.conda\envs\py37\lib\site packages\twisted\internet\base.py”,第765行
引发错误。ReactorNotRestartable()
twisted.internet.error.ReactorNotRestartable
严重:由于未捕获异常而退出
这是调用我的刮皮蜘蛛的脚本。如果我从main打电话给全班同学就可以了

从twisted.internet导入,延迟
从刮擦进口信号
从scrapy.crawler导入爬虫,CrawlerProcess,CrawlerRunner
从scrapy.settings导入设置
从scrapy.utils.project导入获取项目设置
从Scrapers.spider.ScrapeAEA导入scrapeaaspider
AEAMetadata类:
"""
帮助运行scrapeaspider并返回JEL代码和数据链接
对于给定的AEA文章链接。
"""
定义初始化(self,*args,**kwargs):
“初始值设定项”
url=kwargs.get('url')
如果不是url:
raise VALUERROR('未提供文章url')
self.items=[]
def收集_项目(项目、响应、蜘蛛):
self.items.append(项目)
设置=获取项目设置()
爬虫程序=爬虫程序(ScrapeAAsPider,设置)
爬虫。信号。连接(收集物品,信号。物品被刮去)
runner=CrawlerRunner(设置)
d=runner.crawl(爬虫程序,url=url)
d、 addBoth(lambda 2;:reactor.stop())
reactor.run()#脚本将在此阻塞,直到所有爬网作业完成
#进程=爬网进程(设置)
#爬网(爬网程序,url=url)
#process.start()#脚本将在此处阻塞,直到爬网完成
def get_jelcodes(自身):
jelcodes=self.items[0]['jelcodes']
返回JetCodes
def main():
aea=AEAMetadata(url=)https://doi.org/10.1257/app.20180286')
jelcodes=aea.get\u jelcodes()
打印(jelcodes)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
更新了两次实例化AEAMetadata类的简单测试。 以下是我的pywikibot bot中失败的调用代码:

从GetAEAMetadata导入AEAMetadata
def main(*参数):
对于[1,2]中的uu:
打印(“顶部”)
url='1〕https://doi.org/10.1257/app.20170442'
aea=AEAMetadata(url=url)
打印('AEAMetadata'之后)
jelcodes=aea.get\u jelcodes()
打印(jelcodes)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()

我对AEAMetadata的调用嵌入了一个更大的脚本中,这让我误以为AEAMetadata类在失败之前只实例化了一次。 事实上,AEAMetadata被称为两次

而且,我还认为这个脚本会在reactor.run()之后阻塞,因为所有的例子中的注释都说明了这一点。 但是,第二个延迟回调是reactor.stop(),它解除了reactor.run()的阻塞

一个更基本的错误假设是,每次迭代都会删除并重新创建反应器。事实上,反应器是在第一次导入时实例化和初始化的。而且,它是一个全局对象,与底层进程的生命周期一样长,并且不是为重新启动而设计的。删除和重启反应堆实际需要的极端情况如下所述:

所以,我想我已经回答了我自己的问题。 而且,我正在重写我的脚本,这样它就不会试图以一种从未打算过的方式使用反应堆


而且,感谢Gallaecio让我朝着正确的方向思考。

是否多次调用
reactor.run()
?您能否提供一些最小的自包含代码,允许重现问题?()是,“reactor.run()调用了多次吗?”。一定是,但在哪里?由于我的主脚本依赖于pywikibot框架,因此很难提取出一个仍然存在故障的自包含部分。我是Python新手,发现很难浏览库,所以我可能错过了pywikibot使用reactor或脚本使用的habanero库。另一件事是,AEAMetadata由iter调用,这不应该是一个问题,因为在每次迭代中,反应堆都是与类一起创建和删除的。此外,失败发生在第一次迭代中。此外,我将尝试构建一个仍然失败的自包含测试。我认为加拉西奥是对的,我没有提供足够的背景。