Windows中Python3.x下运行Python2.x程序解决方案

Windows中Python3.x下运行Python2.x程序解决方案。

  • 问题描述与分解
    • 场景和适用范围
    • 思路与分解
  • 本文环境介绍
  • 使用pyinstaller打包python2.x下的Scrapy工程
  • 在python 3.x环境下调用exe文件

问题描述与分解

声明:本文实践过程中主要参考博文为https://blog.csdn.net/la_vie_est_belle/article/details/79017358
同时解决了部分上述博文方法在本人项目中无法应对的问题

场景和适用范围

部分库在Python 2.x和Python 3.x下,函数和代码写法有所不同。本文实验室项目希望搭建一个系统,该系统涉及爬虫,分析模型,可视化呈现等模块。其中爬虫先前用的是python 2.7结合Scrapy编写的,而后续由于需要用到tensorflow而使用了python 3.x。由于真的不想改代码,所以整合的时候就遇到了这样的问题,需要在一个环境下实现各部分的功能。

思路与分解

由于我们的爬虫并没有与分析模型和可视化功能模块有直接的数据交互,而是通过mongo数据库间接进行数据交互,因此爬虫模块相对独立,仅需能够正常向数据库写入抓取的数据即可,所以本人希望利用pyinstaller对爬虫模块进行打包,再在python 3.x环境下调用打包好的exe文件运行爬虫模块。所以步骤简单分解为:1、打包python 2.7下使用Scrapy编写的爬虫模块;2、在python 3.x环境下调用exe文件。(如果模块间有频繁数据交互的朋友,这篇文章可能不太适合你,但是可能可以为你提供一种思路,并借助其他工具如redis等建立数据交互的桥梁,其实我也不懂redis怎么用哈哈哈,好了这不是本文重点,如果情况相同就看下文具体操作)

本文环境介绍

本文开发和打包爬虫模块的环境是Anaconda下创建的python 2.7.13
调用爬虫模块exe文件的环境是Anaconda下创建的python 3.5.3

使用pyinstaller打包python2.x下的Scrapy工程

首先在cmd中python 2.7.13环境下安装pyinstaller:

pip install pyinstaller

安装成功后同样在cmd中,将工作目录切换到Scrapy工程下:

cd I:\Proj\exe_test\topic_crawler

本人爬虫目录如下图所示:
Windows中Python3.x下运行Python2.x程序解决方案_第1张图片
图中红线划去部分为与项目模块无关部分。其中Begin.py是项目的起点,也是打包目标。该程序的作用是启动爬虫。启动爬虫的方法有两种,一种是用scrapy中cmdline方法,另一种则是官方文档中给出的。相信很多人和我一样一开始都是使用cmdline的方法去启动一个爬虫,原因很简单,大部分Scrapy教程最开始都是以命令行的方式教学如何启动一个爬虫的。本文也不例外原本代码如下:

 from scrapy import cmdline
 
 commond_list = u"scrapy crawl load_user_location".split()
 cmdline.execute(commond_list)

然而最终你会发现这种方法在打包后完全行不通。(具体报错信息忘了,反正解决不了)
最后还是用了官方文档中启动爬虫的方法,参考文档:https://doc.scrapy.org/en/latest/topics/practices.html
代码如下:

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

process = CrawlerProcess(get_project_settings())
process.crawl('load_user_location')
process.start()

整体的项目路径为:I:\Proj\exe_test\topic_crawler\topic_crawler\spiders
接下来开始打包,结合结构图和上述切换目录的cd操作确认所在目录正确后,在cmd下进行打包:

(python2.7) I:\Proj\exe_test\topic_crawler> pyinstaller Begin.py

很好。大功告成?这么容易?不。pyinstaller真的,真的,以为你只需要Begin.py是不是很傻。假如我们的项目只有单独一个文件,这样的做法确实可行,Begin.exe运行时不会因为缺少模块而报

ImportError: No module named xxx

这样的错误。然而对于项目而言,所需要的模块除了Begin.py中import的库外,还需要项目结构中所有相关的.py文件以及文件中import的库还有这些库中运行所需要调用的所有的模块才能够正常运行。因此在Begin.py中我们需要大量的import项目运行所需要的所有模块
本文参考博文https://blog.csdn.net/la_vie_est_belle/article/details/79017358中博主导入的库,并删去博主项目需要的特定库,这里不再赘述真的是缺啥补啥。
很好终于不会有缺”钙“的情况了。所以可以了?不。。。。。。。。。。。。。。。。
不。。。。。。。。。。。不。。。。。。。。。
给我来了个找不到爬虫的错误。

KeyError:"Spider not found xxxxx"

以为是爬虫没导入于是检查了下Begin.py已经有如下导入

from topic_crawler.spiders import comment
from topic_crawler.spiders import load_user_location

然而还是没用。继续报错,参考了博文https://blog.csdn.net/lynnpaul/article/details/81030413
文中作者也遇到了这样的问题。原文描述是:
“以为到这里就完成了,结果提示:KeyError: ‘Spider not found:’ ,难道是爬虫名不对,重新确认一遍后,没有任何问题,没打包前运行是正常的。尝试了各种方法后发现问题了。
Pyinstaller打包的时候,目录要进入到项目目录中去,不然打包后就容易出这个问题,即进入:Scrapy_Books。”
于是尝试了下。Emmmm我想说大哥真的能行吗。我在每一层都试了一遍,还把源码在生成的目录每一层都放了一遍(就是把源码在每一层文件夹下都放了一份拷贝)。还是没有用,我都尝试过了。头跟我一样铁的可以多试几遍。真的没有用真的。满脑子都是再见小黄脸的表情。。冷静。思考了下本人认为import的文件应该都已经打包进了所生成的文件中,也就是说应该是不需要拷贝其他源码文件了。那为什么会找不到呢???于是本人从Scrapy的配置文件入手,注意到了配置文件settings.py中SPIDER_MODULES变量是个list,而默认list中只有spiders所在目录的路径,讲道理如果scrapy能够扫描该文件夹下所存在的所有spider就不会出现找不到爬虫的问题了,但为啥用list?可能还有别的爬虫文件夹?一个项目把不同爬虫还放在不同目录里好像有点变态啊?算了试试看把爬虫直接加进来。将原本settings.py中的代码
Windows中Python3.x下运行Python2.x程序解决方案_第2张图片
改为
Windows中Python3.x下运行Python2.x程序解决方案_第3张图片
然后再打包。嗯。好的你终于找到爬虫了(我的内心是如此的平静)。在cmd中任意python环境下均可以完美运行你的爬虫项目了(特别提示如果你有传参需求,应注意cmd传入的参数是以gbk编码的,项目中如有解码则需要修改解码方式)。到此为止,打包算是告一段落。

在python 3.x环境下调用exe文件

在cmd中任意python环境下均可以完美运行你的爬虫项目,妥妥的在python 3.x中使用python执行cmd命令不就完事了嘛。os.system(cmd),os.popen(cmd),还是subprocess.Popen()应该都可以的吧??经过尝试,前两种方法真的不会用,运行的结果连基本的settings.py中的配置都是错误的。于是尝试一步一步来首先利用python打开一个cmd窗口

os.system("cmd/c start")

结果发现。cmd窗口中路径前有当前python 3.x环境的路径

(D:\Anaconda\envs\xxxxx) I:\>

抱着尝试的心态在此情况下调用了Begin.exe果不其然真的不行啊。我不要前面这一串路径啊。可能是因为所在运行目录的问题导致运行找不到项目所需的所有内容。通过一番查找在博文https://blog.csdn.net/jtujtujtu/article/details/47949775中发现了所需要的内容。subprocess.Popen()中参数cwd能够设置子进程的当前目录因此对其进行设置,同时为了能够跟踪代码的执行情况,对参数creationflags进行了设置,设置为subprocess.CREATE_NEW_CONSOLE从而创建了新的cmd窗口并运行进程显示进程输出内容,调用代码如下

import subprocess
command = [r"I:\Proj\exe\topic_crawler\dist\Begin\Begin.exe"]
subprocess.Popen(command, bufsize=0, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=False, shell=False,
                 cwd=r"I:\Proj\exe\topic_crawler\dist\Begin",
                 env=None, universal_newlines=False,
                 startupinfo=None,
                 creationflags=subprocess.CREATE_NEW_CONSOLE)

Done。有疑问请咨询QQ: 429062304

你可能感兴趣的:(Python)