首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用BeautifulSoup、Platypus和Python3的Unicode差异

使用BeautifulSoup、Platypus和Python3的Unicode差异
EN

Stack Overflow用户
提问于 2018-03-20 21:31:51
回答 1查看 124关注 0票数 0

这里有一个我没想到的具体问题。

我使用Platypus从python脚本创建Mac可执行文件,这样我的同事就可以更容易地使用它们。应我们团队中另一个程序员的请求,我正在使用Python3 (3.6.0)。当前的任务包括为链接抓取大量本地XML和HTML文件。我使用BeautifulSoup 4.6作为这个部分,按照Soup本身的建议,通过2到3转换为Python3。

下面是脚本,缩小到失败的部分,并以原始的方式接收一些其他的参数。

代码语言:javascript
复制
import sys
import os
import argparse
from bs4 import BeautifulSoup
import xml.etree.ElementTree as ET
from glob import glob

# Main function
def runTest(args):

    # Handle arguments and flags
    parser = argparse.ArgumentParser()
    parser.add_argument('-links', action='store_true')
    parser.add_argument('file_names', nargs='*')

    # "extra" will help us deal with out-of-order arguments.
    args, extra = parser.parse_known_args(args)

    print('Args:')
    print(args)
    print('Extra:')
    print(extra)

    if args.links:

        # Replace arguments with wildcards with their expansion.
        # If a string does not contain a wildcard, glob will return it as is.
        # Mostly important if we run this on Windows systems.
        file_names = list()
        for arg in args.file_names:
            file_names += glob(arg)
        for item in extra:
            file_names += glob(item)

        # Don't run the script on itself.
        if sys.argv[0] in file_names:
            file_names.remove(sys.argv[0])

        # If the filenames don't exist, say so and quit.
        if file_names == []:
            sys.exit('No file or directory found by that name.')

        for name in file_names:
            print('Filename: ' + name)
            # The line below fails on Unicode files, but only in Platypus.
            soup = BeautifulSoup(open(name), 'html.parser')
            print('HTML:')
            print(str(soup))

if __name__ == "__main__":
    # this won't be run when imported
    runTest(sys.argv)

这里有一个简单的HTML文件来说明这个问题。你可能会猜到这件事会在哪里失败。

代码语言:javascript
复制
<p>I am a simple HTML snippet øÆü <a href="https://totally.legit.link" target="_blank">Link text</a></p>

如果我通过终端运行我的脚本,它工作100%好。

但是,如果我用Platypus包装代码,它会引发一个错误:

代码语言:javascript
复制
Traceback (most recent call last):
  File "/Users/cfred/Documents/GitHub Repositories/hx-py/XML_utilities/platypus_test/Ptest.app/Contents/Resources/script", line 52, in <module>
    runTest(sys.argv)
  File "/Users/cfred/Documents/GitHub Repositories/hx-py/XML_utilities/platypus_test/Ptest.app/Contents/Resources/script", line 46, in runTest
    soup = BeautifulSoup(open(name), 'html.parser')
  File "/Users/cfred/Documents/GitHub Repositories/hx-py/XML_utilities/platypus_test/Ptest.app/Contents/Resources/bs4/__init__.py", line 191, in __init__
    markup = markup.read()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 30: ordinal not in range(128)

是的-就在那。

如果出现在这两种情况下,这个错误对我来说都是有意义的,但是只有当脚本在Platypus中运行时,它才会出现。以前我从来没有让鸭嘴兽运行过与终端不同的东西,所以我对这个特殊的问题一无所知。

我已经将鸭嘴兽设置为使用/usr/local/bin/python3,而不是它通常的/usr/bin/python,所以也许这有什么关系吗?对于python3,还有别的地方可以指点吗?

欢迎提出建议。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-20 21:55:32

open(name)返回的类似文件的对象将使用解释器定义的编码或在其中运行的环境将字节转换为字符。当编码与文件内容不匹配时,这将使程序以不一致的方式失败,因为当程序在不同的解释程序或环境中运行时,将使用不同的编码。

不要在没有要打包和分发的代码中显式编码的情况下打开文本文件。相反,请使用open(name, encoding=some_encoding)。如果您知道,请为该文件选择正确的编码(html文件应该在头中声明编码)。如果您不这样做,使用一些您认为通常适合您的目标受众和用例的编码。在大多数情况下,'utf8'是最好的选择。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49394453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档