我需要先用回调函数 callback 改变类变量,然后使用类变量,但发现程序的实际执行是不等待 yield Request(url,callback)中的 callbak 函数执行完成,便执行其后的语句了。怎么办呢?
写了个程序来表达我的意图:
# -*- coding: utf-8 -*-
from scrapy import Spider, Request
class ZhihuSpider(Spider):
name = "debug_zhihu"
allowed_domains = ["www.zhihu.com"]
list_for_test = []
def start_requests(self):
yield Request('https://www.zhihu.com/people/excited-vczh/following', self.change_list)
print('after sent Request statement,list_for_test:', self.list_for_test)
# 想打印出“[0,1,2,3,4]”,结果打印出"[]"
def change_list(self):
for each_item in range(0, 5):
self.list_for_test.append(each_item)
1
scb20100708 OP 发现补充中的代码错了,def change_list(self):应是 def change_list(self,response):
改后也输出不了想输出的"[0,1,2,3,4]" |
2
leavic 2017-11-17 14:50:25 +08:00
把 print 写进 callback 函数的最后。。。。。
|
3
scb20100708 OP @leavic
还有别的方法吗?实际代码还有函数“ change_list2 ”也要改变类变量,想在所有改变执行完后再处理类变量。 |
4
860670496 2017-11-17 15:21:30 +08:00
请参考:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317799226173f45ce40636141b6abc8424e12b5fb27000 如果一个函数定义中包含 yield 关键字,那么这个函数就不再是一个普通函数,而是一个 generator: 这里,最难理解的就是 generator 和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next()的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行。 所以直接用啃 scrapy 的方法来学 python 不是个好选择,这个坑我也掉过,就是看教程的时候完全是表面上的理解生成器的概念,一用起来就傻了,必须得动手写几个才能彻底明白 |
5
knightdf 2017-11-17 15:36:36 +08:00
把 yield Request(url,callback)其后的语句放在 callback 的后面执行
|
6
leavic 2017-11-17 15:50:23 +08:00 1
@scb20100708 没有什么好方法了,你的需求就应该是把函数放进 callback 里面。
|
7
iyaozhen 2017-11-17 16:05:06 +08:00 via Android
只能 callback 吧。回调地狱就是那么来的
|
8
scb20100708 OP |
9
hcnhcn012 2017-11-17 19:29:44 +08:00 via iPhone
机制就是这样,为了效率,要是你 callback 里面花了一个很长时间的的 IO 操作,整个框架都在等你的 callback 然后 yield 带出从而发生阻塞那效率会很低,具体怎么实现的话就要结合 twisted 看源码了
|
10
RadishWind 2017-11-17 19:32:43 +08:00
还没有实验 加个修饰器行不行?在修饰器中等待?
|
11
zhijiansha 2017-11-17 19:46:01 +08:00
scrapy 是异步的,reuqest 请求也是放进队列的
|
12
larsenlouis 2017-11-17 20:24:37 +08:00 1
“回调函数 callback 改变类变量,然后使用类变量”
是发出单个请求->callback 链->print,还是发出所有的请求->完成每个请求的 callback 链->print ? 后者可以用 def spider_closed(self, spider) 参考 https://doc.scrapy.org/en/latest/topics/signals.html |
13
scb20100708 OP |
14
scb20100708 OP @larsenlouis
谢谢,我想要实现的正是你说的“发出所有的请求->完成每个请求的 callback 链->print ? “。 方法可行,谢谢啦。 还找到了一个办法,直接在类中加个函数: def closed(self, reason): print(list_for_test) 参考: https://stackoverflow.com/a/33312325/7011350 |