《Python Cookbook(第2版)中文版》——1.11 检查一个字符串是文本还是二进制

1.11 检查一个字符串是文本还是二进制

任务

在Python中,普通字符串既可以容纳文本,也可以容纳任意的字节,现在需要探知(当然,完全是启发式的试探:对于这个问题并没有什么精准的算法)一个字符串中的数据究竟是文本还是二进制。

解决方案

我们采取Perl的判定方法,如果字符串中包含了空值或者其中有超过30%的字符的高位被置1(意味着该字符的码值大于126)或是奇怪的控制码,我们就认为这段数据是二进制数据。我们得自己编写代码,其优点是对于特殊的程序需求,我们随时可以调整这种启发式的探知方式:

from _ _future_ _ import division           # 确保/不会截断
import string
text_characters = "".join(map(chr, range(32, 127))) + "\n\r\t\b"
_null_trans = string.maketrans("", "")
def istext(s, text_characters=text_characters, threshold=0.30):
      # 若s包含了空值,它不是文本
      if "\0" in s:
             return False
      # 一个“空”字符串是“文本”(这是一个主观但又很合理的选择)
      if not s:
            return True
      # 获得s的由非文本字符构成的子串
      t = s.translate(_null_trans, text_characters)
      # 如果不超过30%的字符是非文本字符,s是字符串
      return len(t)/len(s) <= threshold

讨论

可以轻易地修改函数istext的启发式探知部分,只需传递一个指定的阀值作为判断某字符串所含数据是“文本”(即正常的ASCII字符加上4个“正常”的控制码,在文本中这几个控制码都是有意义的)的基准,默认的阀值是0.30(30%)。举个例子,如果期望它是采用了iso-8859-1的意大利文本,可以给text_characters参数添加意大利语中的一些重音字母,“àèéìòù”。

很多时候,需要检查的对象是文件,而不是字符串,也就是说要判断文件中的内容是文本还是二进制数据。同样地,我们仍可采用Perl的启发式方法,用前面提供的istext函数来检查文件的第一个数据块:

def istextfile(filename, blocksize=512, **kwds):
     return istext(open(filename).read(blocksize), **kwds)

注意,默认情况下,istext函数中的len(t)/len(s)将被截断成0,因为这是一个整数之间的除法结果。以后的版本(估计是Python 3.0,几年后发布),Python中的/操作符的意义会被改变,这样我们在做除法运算的时候就不会发生截断—如果你确实需要截断,可以用截断除法操作符//。

不过,现在Python还没有改变除法的语义,这是为了保证一定的向后兼容性。为了让成千上万行的现有的Python程序和模块平滑地工作于所有的Python 2.x版本,这非常重要。不过,对于语言版本的主版本号的改变,Python允许进行不考虑向后兼容性的改变。

因此,对于本节的解决方案中的模块,按照未来版本中计划的行为模式来改变除法的行为是非常方便的,我们用这种方式来引入模块:

from _ _future_ _ import division

这条语句并不影响程序的其余部分,只影响紧随此声明的模块;通过这个模块,/表现得像“真实的除法”(没有截断)。对于Python 2.3和2.4,dvision可能是唯一需要从 _future _导入的模块。其他的一些未来版本中计划的特性,nested_scope和生成器,现在已经是语言的一部分了,因而无法被关闭—当然明确导入它们没有什么坏处,但只有在你的程序需要能够运行在老版本的Python环境下时,这种做法才有意义。

时间: 2024-10-02 21:45:07

《Python Cookbook(第2版)中文版》——1.11 检查一个字符串是文本还是二进制的相关文章

《“笨办法”学Python(第3版)》——习题6 字符串和文本

习题6 字符串和文本 虽然你已经在程序中写过字符串了,但是你还不了解它们的用处.在这个习题中我们将使用复杂的字符串来建立一系列变量,从中你将学到它们的用途.首先,我们解释一下字符串是什么. 字符串通常是指你想要展示给别人的或者是想要从程序里"导出"的一小段字符.Python可以通过文本里的双引号(")或者单引号(')识别出字符串来.这在以前的打印练习中你已经见过很多次了.如果你把单引号或者双引号括起来的文本放到print后面,它们就会被Python打印出来. 字符串可以包含之

《Python Cookbook(第2版)中文版》——导读

前 言 这本书不是一本典型的O'Reilly风格的书,而是一本集合了多个作者的手稿的作品.实际上,这也是一种将开源开发的方式应用到书籍出版业的尝试.Python社区有超过300个成员在本书中贡献了他们的心得和资料.在这里,我们作为编辑,想给你--本书的读者,介绍一些重要的背景资料,这些背景资料是关于此书是如何编著出来,以及这个过程和涉及的人,并提出一些关于这种崭新的风格的思考. 目 录 [第1章 文本1.1 每次处理一个字符](https://yq.aliyun.com/articles/963

《Python Cookbook(第2版)中文版》——1.8 检查字符串中是否包含某字符集合中的字符

1.8 检查字符串中是否包含某字符集合中的字符 任务 检查字符串中是否出现了某字符集合中的字符. 解决方案 最简单的方法如下,兼具清晰.快速.通用(适用于任何序列,不仅仅是字符串,也适用于任何容器,不仅仅是集合): def containsAny(seq, aset): """ 检查序列seq是否含有aset中的项 """ for c in seq: if c in aset: return True return False 也可以使用更高级和

《Python Cookbook(第3版)中文版》——6.11 读写二进制结构的数组

6.11 读写二进制结构的数组 6.11.1 问题 我们想将数据编码为统一结构的二进制数组,然后将这些数据读写到Python元组中去. 6.11.2 解决方案 要同二进制数据打交道的话,我们可以使用struct模块.下面的示例将一列Python元组写入到一个二进制文件中,通过struct模块将每个元组编码为一个结构. from struct import Struct def write_records(records, format, f): ''' Write a sequence of t

《Python Cookbook(第3版)中文版》——导读

前 言 自2008年以来,我们已经目睹了整个Python世界正缓慢向着Python 3进化的事实.众所周知,完全接纳Python 3要花很长的时间.事实上,就在写作本书时(2013年),大多数Python程序员仍然坚持在生产环境中使用Python 2.关于Python 3不能向后兼容的事实也已经做了许多努力来补救.的确,向后兼容性对于任何已经存在的代码库来说是个问题.但是,如果你着眼于未来,你会发现Python 3带来的好处绝非那么简单. 正因为Python 3是着眼于未来的,本书在之前的版本上

《Python Cookbook(第2版)中文版》——第1章 文本 1.1 每次处理一个字符

第1章 文本 引言 感谢:Fred L. Drake, Jr.,PythonLabs 对于脚本语言来说,文本处理任务构成了一个重要的组成部分,每个人都会同意文本处理非常有用.每个人都会有一些文本需要重新格式化或者转化为另一种形式.问题是,每个程序都与另一个程序有点不同,无论它们是多么相似,想提取出一些可复用的代码片段并用它来处理不同的文件格式仍然是非常困难的. 什么是文本 看起来问题有点简单得过分了,事实上,我们看到了文本,就知道了什么是文本,文本是一串字符,这正是它与二进制数据之间的不同.二进

《Python Cookbook(第2版)中文版》——1.18 一次完成多个替换

1.18 一次完成多个替换 任务 你想对字符串的某些子串进行替换. 解决方案 正则表达式虽然不易读懂,但有时它的确是最快的方法.re对象(标准库中的re模块)提供的强大sub方法,非常利于进行高效的正则表达式匹配替换.下面给出一个函数,该函数返回一个输入字符串的拷贝,该拷贝中的所有能够在指定字典中找到的子串都被替换为字典中的对应值: import re def multiple_replace(text, adict): rx = re.compile('|'.join(map(re.escap

《Python Cookbook(第2版)中文版》——1.7 将字符串逐字符或逐词反转

1.7 将字符串逐字符或逐词反转 任务 把字符串逐字符或逐词反转过来. 解决方案 字符串无法改变,所以,反转一个字符串需要创建一个拷贝.最简单的方法是使用一种"步长"为-1的特别的切片方法,这样可立即产生一个完全反转的效果: revchars = astring[::-1] 如果要按照单词来反转字符串,我们需要先创建一个单词的列表,将这个列表反转,最后再用join方法将其合并,并在相邻两词之间都插入一个空格: revwords = astring.split( ) # 字符串->

《Python Cookbook(第2版)中文版》——1.23 对Unicode数据编码并用于XML和HTML

1.23 对Unicode数据编码并用于XML和HTML 任务 你想对Unicode文本进行编码,使用一种有限制,但很流行的编码,如ASCII或Latin-1,并将处理后的结果用于HTML输出或者某些XML应用. 解决方案 Python提供了一种编码错误处理工具,叫做xmlcharrefreplace,它会将所有不属于所选编码的字符用XML的数字字符引用来替代: def encode_for_xml(unicode_data, encoding='ascii'): return unicode_