Buildozer编译apk,但它在android上崩溃

时间:2014-05-30 10:32:03

标签: android python-2.7 beautifulsoup apk kivy

我能够构建一个.apk,但是在我安装到我的Android手机上后,它只是在启动时崩溃了。我失败的想法是我使用第三方库,例如(beautifulsoup)。

这是我的导入在main.py中的显示方式:

from kivy.app import App
from kivy.properties import ListProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.scrollview import ScrollView
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition

import time, os, random, urllib2, re, cookielib as cj

from bs4 import BeautifulSoup as bs
from functools import partial

我正在运行小牛10.9.3

是否与buildozer.spec文件有关? 我尝试将BeautifulSoup添加到应用程序要求中,但它并没有改变任何东西。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:5)

我也遇到了这个问题,但我(显然)能够通过解决方法让一切正常。由于它看起来不像你发布了一个logcat,我会假设你遇到了我遇到的同样问题。

是的,您需要在规范中列出beautifulsoup4作为要求。从查看bs4的代码来看,看起来bs4愿意使用几个“构建器”中的任何一个。它支持HTMLParser,html5lib或lxml。我不知道为什么我们不能加载HTMLParser,但它实际上是三个中的最少首选库,如果它不是因为导入没有尝试阻止的事实,它似乎一切都会正常工作(只要其他解析库之一可用)。

考虑到这一点,我包含了其他一个库,我决定破解导入过程,以便Python假装_htmlparser加载好了:)

这篇文章很有启发性:http://xion.org.pl/2012/05/06/hacking-python-imports/

最终结果如下:

import imp
import sys

class ImportBlocker(object):

    def __init__(self, *args):
        self.black_list = args

    def find_module(self, name, path=None):
        if name in self.black_list:
            return self

        return None

    def load_module(self, name):
        module = imp.new_module(name)
        module.__all__ = [] # Necessary because of how bs4 inspects the module

        return module

sys.meta_path = [ImportBlocker('bs4.builder._htmlparser')]
from bs4 import BeautifulSoup

我还在buildozer.spec中添加了html5lib。

现在,这是解决问题的正确方法吗?我不知道。最好的方法可能是请求作者修复它。将导入放在try块中可能很简单。尽管如此,这是我目前使用的方法,它至少是一个有趣的练习,是一种测试你的应用程序的方法,直到更好的解决方案出现。

另外,我应该警告你,我最近才这样做,所以我不能100%保证它不会导致任何问题,但至少,它能够很好地运行并抓取我的应用程序我感兴趣的特定网站。祝你好运!

答案 1 :(得分:0)

我知道这个问题已有几年了。我认为@Will给出的答案很棒,但不幸的是,在我的情况下,我无法使用它,因为html5lib对于我的制作来说太慢了。所以这是供参考的;对于任何绝对必须使用内置解析器的人。它不漂亮,但它相当易于管理。

问题

经过多次调查,我找到了问题的原因。在buildozer日志中,我注意到编译_htmlparser文件时出现问题,日志读数如下(我的项目路径替换为< project-path>):

Compiling <project-path>/.buildozer/android/platform/build/dists/mypackage/private/lib/python2.7/site-packages/bs4/builder/_htmlparser.py ...
SyntaxError: ("(unicode error) \\N escapes not supported (can't load unicodedata module)", ('<project-path>/.buildozer/android/platform/build/dists/mypackage/private/lib/python2.7/site-packages/bs4/builder/_htmlparser.py', 135, None, 'data = u"\\N{REPLACEMENT CHARACTER}"\n'))

因为它无法编译,所以它不包含在构建的apk文件中。所以我查看了导致问题的文件和行:data = u"\N{REPLACEMENT CHARACTER}"实际上应该被data = u"\ufffd"替换

快速修复

现在,简单的方法是在包中修改文件。您可以编辑上面错误中提到的文件,理论上该文件应该可以工作,但不建议这样做,因为每次重新安装软件包或从另一台机器构建代码时问题都会回来。< / p>

边缘更好地修复

如果将修复程序全部打包到我们的代码中会很好,所以从@ Will的答案中汲取灵感,这是您在bs4导入之前需要输入的代码:

import sys

class ImportFixer(object):
    def __init__(self, mname):
        self.mname = mname

    def find_module(self, name, path=None):
        if name == self.mname:
            return self
        return None

    def load_module(self, name):
        import _htmlparser as module
        module.__name__ = name
        return module

sys.meta_path = [ImportFixer('bs4.builder._htmlparser')]
from bs4 import BeautifulSoup

主要区别在于您需要将_stmlparser.py文件从bs4包复制到当前目录,并使用data = u"\N{REPLACEMENT CHARACTER}"

修复前面提到的行data = u"\ufffd"

然后,每次导入bs4模块时,都会神奇地拦截导入并使用本地文件。

警告:如果您更新了Beautiful Soup,您可能需要在项目中使用更新的_htmlparser.py文件,并根据需要进行相同的修复。

最终评论

如果我犯了一些拼写错误,语法错误或根本没有意义,请记住我周末大部分时间都在解决这个问题,坦率地说,我并没有直接思考。评论如果您有任何问题,我会在有机会时回复和/或编辑我的答案。