python首次使用generator时遇到的问题
1. 因为刚开始开发python程序不久就遇到了一个generator的问题,python有的特性还是和java有所区别,记录一下这个问题
def parse(self, response): self.logger.info("smzdm_jingxuan spider starting") self.broswer.get('https://www.smzdm.com/jingxuan/') last_height = self.broswer.execute_script("return document.body.scrollHeight") print(last_height) count = 0 while True: if count == 30: break self.broswer.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(2) new_height = self.broswer.execute_script("return document.body.scrollHeight") if new_height == last_height: break last_height = new_height time.sleep(1.2) count = count + 1 source = self.broswer.page_source self.logger.info('before parse goods in page') try: # return self.parse_goods_in_page(source) self.parse_goods_in_page(source) except Exception as e: def parse_goods_in_page(self, source):
def parse_goods_in_page(self, source): print('parse_goods_in_page in') self.logger.info("parse_goods_in_page in in") scrapy_selector = Selector(text=source) items_selector = scrapy_selector.xpath('//div[@class="z-feed-content"]') self.logger.info('Theres a total of ' + str(len(items_selector)) + ' links.') s = 0 for item_selector in items_selector: try: self.logger.info("s=" + str(s)) ....... ....... s = s + 1 yield smzdm_item except Exception as e: self.logger.info('Reached last iteration #' + e.__traceback__ + str(s)) self.broswer.close() return
现象是在parse()中调parse_goods_in_page(),发现调不到,打断点跟踪也进不去方法。因为java没有这样的特性所以一开始有点懵。后来查了资料,在《Python Cookbook》中有说到
“The mere presence of the yield statement in a function turns it into a generator. Unlike a normal function, a generator only runs in response to iteration”
Excerpt From: David Beazley and Brian K. Jones. “Python Cookbook.” Apple Books.
也就是说,关键字yield说明parse_goods_in_page这个方法是个generator。而直接调用generator方法,如代码中 self.parse_goods_in_page(source)这种不会运行这个方法,而只是返回了一个generator。如 gen = self.parse_goods_in_page(source), 可以看到里面的日志没有输出。要运行的话只能next(gen),此时代码会跑到 yield smzdm_item 然后返回,如果再运行一次 next(gen),代码从yield smzdm_item后继续第二次循环到yield smzdm_item返回。
那我想调用parse_goods_in_page这个方法希望它一下子整个执行完怎么办呢,可以把self.parse_goods_in_page(source)这句改成yield from self.parse_goods_in_page(source)[https://www.python.org/dev/peps/pep-0380/]或 return self.parse_goods_in_page(source)
2. 需要注意以下代码
def parse_goods_in_page(self, page_items_selector_list): ... for t in create_time_text: if t.strip(): item_create_time = t.strip() self.logger.info("create_time = " + item_create_time) smzdm_item['item_create_time'] = item_create_time # 拼多多的create_time和其他的不太一样 self.logger.info("item_create_time = " + str(item_create_time)) if not item_create_time: create_time_text = item_selector.css(".wechat-time::text").get() self.logger.info("pdd create_time_text = " + str(create_time_text)) item_create_time = create_time_text.strip() self.logger.info("create_time = " + item_create_time) ........ s = s + 1 yield smzdm_item
在开发过程中发现item_create_time没有赋值的情况下(没进入到for t in create_time_text),执行到if not item_create_time时没有报错(变量未被赋值时这个变量应该不存在),打印出来后确实有值。注意到这个方法是个generator,那前面next跑了一次,接下来next时这个item_create_time其实是上一次的值。所以要避免这个问题在方法前面可以先给item_create_time初始化一下
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人