【问题标题】:Python on Appengine using BeautifulSoup ImportError: No module named bs4Appengine 上的 Python 使用 BeautifulSoup ImportError:没有名为 bs4 的模块
【发布时间】:2015-01-02 03:54:40
【问题描述】:

EDIT2:已解决!请参阅下面有关正确导入的答案。 from lib.bs4 import BeautifulSoup 而不仅仅是 from bs4 import BeautifulSoup

编辑:将 bs4 放在项目的根目录中似乎可以解决问题;但是,它不是一个理想的结构。因此,我将保留此问题以尝试找到更强大的解决方案。

过去有人问过这个问题的变体,但那里的解决方案似乎不起作用。老实说,我不确定这是否是因为 BeautifulSoup 或 Appengine 的变化。

请参阅:Python 2.7 : How to use BeautifulSoup in Google App Engine?How to include third party Python libraries in Google App Engine?Which version of BeautifulSoup works with GAE (python 2.5)?

Lipis 提出的解决方案似乎是将 3rd 方库添加到项目根目录下的 libs 文件夹中,然后将以下内容添加到主应用程序中:

import sys
sys.path.insert(0, 'libs')

目前,我的结构是这样的:

ntj-test
├── lib
│   └── bs4 
├── templates
├── main.py
├── get_data.py 
└── app.yaml

这是我的 app.yaml:

application: ntj-test
version: 1
runtime: python27
api_version: 1
threadsafe: yes

handlers:
- url: /favicon\.ico
  static_files: favicon.ico
  upload: favicon\.ico

- url: .*
  script: main.app

libraries:
- name: webapp2
  version: latest
- name: jinja2
  version: latest

这是我的 main.py:

import webapp2
import jinja2
import get_data
import sys

sys.path.insert(0, 'lib')

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader('templates'),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True,
)


class MainHandler(webapp2.RequestHandler):
    def get(self):

        teamName = get_data.all_coach_data()[1]
        coachName = get_data.all_coach_data()[2]
        teamKey = get_data.all_coach_data()[0]

        values = {
            'coachName': coachName,
            'teamName': teamName,
            'teamKey': teamKey,
        }

        template = JINJA_ENVIRONMENT.get_template('index.html')
        self.response.write(template.render(values))

app = webapp2.WSGIApplication([
    ('/', MainHandler)
], debug=True)

get_data.py 将正确的数据返回给我的变量以填充值,我已在调试器中验证了这一点。

在我的开发环境中启动 main.py 时出现问题(我还没有上传到 gcloud)。毫无疑问,无论我通过上述链接或在我的谷歌搜索中发现了哪些漂亮的技巧,终端总是返回:

Import Error: No module named bs4

在上面的一个 SO 链接中,评论者说“GAE 仅支持纯 Python 模块。bs4 不是纯的,因为某些部分是用 C 编写的。”我不确定这是否属实,我不确定如何验证它。我没有足够的声誉来发表评论以找出答案。 :(

我浏览了 Crummy 网站上的 bs4 文档,阅读了所有相关的 SO 问题和答案,并尝试从 Appengine 的文档中收集提示。但是,我一直找不到不涉及使用已弃用的 BeautifulSoup 版本的解决方案,它没有我需要的功能。

我是编程和使用 StackOverflow 的初学者,所以如果我遗漏了一些重要信息或没有遵循问题的良好做法,请告诉我。我将在必要时编辑并添加其他信息。

谢谢!

编辑: 我不确定 get_data 代码是否过大,但这里是:

from bs4 import BeautifulSoup
import urllib2, re

teamKeys = {
    'ATL': 'Atlanta Falcons',
    'HOU': 'Houston Texans',
}

def get_all_coaches():
    for key in teamKeys:
        page = urllib2.urlopen("http://www.nfl.com/teams/coaches?coaType=head&team=" + key)
        soup = BeautifulSoup(page)
        return(head_coach(soup))

def head_coach(soup):
    head = soup.select('.coachprofiletext p')[0].text
    position, name = re.split(': ', head)
    return name

def export_coach_data():
    testList = []
    for key in teamKeys:
        page = urllib2.urlopen("http://www.nfl.com/teams/coaches?coaType=head&team=" + key)
        soup = BeautifulSoup(page)
        teamKey = key
        teamName = teamKeys[key]
        headCoach = head_coach(soup)

        t = [
            teamKey,
            teamName,
            str(headCoach),
        ]

        testList.append(t)

    return(testList)

def all_coach_data():
    results = data.export_coach_data()

    ATL = results[0]
    HOU = results[1]

    return ATL

我想指出,这可能是因为执行不力(我只是在业余时间认真开发了几个月),但它确实将正确的值返回给我的 main.js 变量。

这是 Appengine 启动器日志:

2014-11-05 15:36:53 Running command: "['C:\\Python27\\pythonw.exe', 'C:\\Program Files\\Google\\Cloud SDK\\google-cloud-sdk\\platform\\google_appengine\\dev_appserver.py', '--skip_sdk_update_check=yes', '--port=11080', '--admin_port=8003', u'G:\\projects\\coaches']"
INFO     2014-11-05 15:37:00,119 devappserver2.py:725] Skipping SDK update check.
WARNING  2014-11-05 15:37:00,157 api_server.py:383] Could not initialize images API; you are likely missing the Python "PIL" module.
INFO     2014-11-05 15:37:00,190 api_server.py:171] Starting API server at: http://localhost:19713
INFO     2014-11-05 15:37:00,210 dispatcher.py:183] Starting module "default" running at: http://localhost:11080
INFO     2014-11-05 15:37:00,216 admin_server.py:117] Starting admin server at: http://localhost:8003
ERROR    2014-11-05 20:37:48,726 wsgi.py:262] 

Traceback (most recent call last):

  File "C:\Program Files\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\google\appengine\runtime\wsgi.py", line 239, in Handle

    handler = _config_handle.add_wsgi_middleware(self._LoadHandler())

  File "C:\Program Files\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\google\appengine\runtime\wsgi.py", line 298, in _LoadHandler

    handler, path, err = LoadObject(self._handler)

  File "C:\Program Files\Google\Cloud SDK\google-cloud-sdk\platform\google_appengine\google\appengine\runtime\wsgi.py", line 84, in LoadObject

    obj = __import__(path[0])

  File "G:\projects\coaches\main.py", line 3, in <module>

    import get_data

  File "G:\projects\coaches\get_data.py", line 1, in <module>

    from bs4 import BeautifulSoup

ImportError: No module named bs4

INFO     2014-11-05 15:37:48,762 module.py:652] default: "GET / HTTP/1.1" 500 -

【问题讨论】:

  • 您实际上是如何进行导入的? “从 bs4 导入 BeautifulSoup”?
  • 您可以手动解析 HTML 或通过查找模式提取您要查找的内容。
  • 您进行导入的代码在哪里?
  • 你是如何“启动”main.py的。你不会像“python main.py”一样运行它吗?
  • 我会更新我的帖子来回答这些问题。

标签: python google-app-engine python-2.7 beautifulsoup


【解决方案1】:

我认为您的问题是 main.py 中的一个错字:

sys.path.insert(0, 'lib')

您的目录是libs,而不是lib

【讨论】:

  • 那个目录结构有错字。该文件夹在我的项目中名为 lib ,但我从另一个问题中复制了该结构。我已经编辑了原始帖子。
  • 这不是答案。这只是一个错字。可以删除吗?
【解决方案2】:

好的,还有一些其他的修复。在库下的 app.yaml 中导入 lxml:

libraries:
- name: lxml
  version: "2.3" <<- do NOT use "latest"

确保您在 lib 中有一个 __init__.py 文件。我在那里添加了一些代码以使其自连接:

import os
import sys

libs_directory = os.path.dirname(os.path.abspath(__file__))
if libs_directory not in sys.path:
    sys.path.insert(0, libs_directory)

root_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if root_directory not in sys.path:
    sys.path.insert(0, root_directory)

【讨论】:

  • 我需要对 init.py 文件进行任何修改吗?如果没有,我已经进行了这些更改,并且我得到了同样的错误。我应该从 main.py 文件中删除 sys.path.insert 吗?感谢您的帮助!
  • __init__.py 中的代码不是必须的。您的sys.path.insert(0, 'lib') 方法应该有效。你安装的是什么版本的bs4? (打开其__init__.py 进行检查。)您是否在 app.yaml 中将 lxml 添加到您的-libraries 中?
  • 我确实将 lxml 添加到了我的 app.yaml 库中。当然,我删除了 version = "4.3.2"。我已经尝试使用和不使用您在上面发布的代码的 lib/__init__.py 文件,但均未成功。编辑:我已经用我当前的代码更新了 GH 存储库。
  • sys.path.insert(0, 'lib') 之后添加:import logging logging.info(sys.path) 以检查可用的模块
  • 好的,我已经完成了,运行应用程序时出现了同样的错误。我在哪里可以找到日志?根据“print sys.path”,它应该是我的根目录,但那里没有任何日志。
【解决方案3】:

编辑:有人指出这有点骇人听闻。如果是这样,如何修改此解决方案以不需要重命名 BS4 内的模块?

http://www.reddit.com/r/learnpython 的几个用户帮助我解决了这个问题。

通过扩展 Lipis 提出的解决方案,我们在 main.py 中添加了以下内容:

import os, sys

rootdir = os.path.dirname(os.path.abspath(__file__))
lib = os.path.join(rootdir, 'lib')
sys.path.append(lib)

然后,这里没有人在这里或任何其他 SO 答案中提到过,我将“lib.bs4”添加到我的所有导入语句中,如下所示:

from lib.bs4 import BeautifulSoup

但是,不仅如此,在 bs4 库本身中还有对 bs4 的引用,所以我搜索并用 lib.bs4.&lt;something&gt; 替换了所有这些。

现在,我的应用程序终于运行了,结构也组织好了。所有功劳归于/u/invalidusemame/u/prohulaelk

希望这篇文章可以帮助陷入类似情况的其他人。也许应该很明显,所有导入都需要添加到 import 语句中,但从所有答案中并不是很明显。

感谢所有帮助解决问题的人!

【讨论】:

  • 如果您正确地将lib 添加到您的系统路径,您就不必在任何地方添加lib.bs4。不正确的解决方案。当你更新 bs4 时,你所有的路径都会回到你原来的位置。 -1
  • 我仍然将 lib 添加到 sys.path。什么做得不好?我理解您的担忧,但我不确定解决方案是什么。
【解决方案4】:

或者,您可以创建一个名为 appengine_config.py 的文件来加载第三方库。此文件将在启动新实例时加载。

import sys
import os.path
# add `lib` subdirectory to `sys.path`, so our `main` module can load third-party libraries.
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib'))

【讨论】:

    猜你喜欢
    • 2012-07-31
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 2019-03-14
    • 1970-01-01
    • 2014-10-31
    • 2020-07-28
    相关资源
    最近更新 更多