Python踩坑指南(第二季)

本期围绕jieba讲一个我遇到的实际问题,在同一个服务里,存在两个不同接口A和B,都用到了jieba分词,区别在于两者需要调用不同的词库,巧合中,存在以下情况:

词库A:"干拌面"
词库B:"干拌","面"

在服务启动的时候,由于词库A优先被加载了,再去加载词库B的时候发现,并没有加载成功:

接口A中:

jieba.load_userdict("A.txt")

接口B中:

jieba.load_userdict("B.txt")

结果发现,在切干拌面这个词的时候,接口B中还是没有切成功。其实每次在我们加载jieba的时候,可以注意一下会出现以下info:

Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/hv/kfb7n4lj06590hqxjv6f3dd00000gn/T/jieba.cache
Loading model cost 0.824 seconds.
Prefix dict has been built succesfully.

显而易见,先进行了Building prefix dict,再Dumping model to file cache,后续Loading model都会来自这,所以这个地方导致以上问题。

我是这么处理的:
接口A中:

jieba1 = jieba.Tokenizer(dictionary="A.txt")

接口B中:

jieba2 = jieba.Tokenizer(dictionary="B.txt")

案例如下:

In [1]: import jieba

In [2]: jieba1=jieba.Tokenizer(dictionary="A.txt")

In [3]: jieba2=jieba.Tokenizer(dictionary="B.txt")

In [4]: jieba1.lcut("干拌面")
Building prefix dict from /Users/slade/Desktop/A.txt ...
Dumping model to file cache /var/folders/hv/kfb7n4lj06590hqxjv6f3dd00000gn/T/jieba.u5221c1b70f06b36e44bc519f39715c96.cache
Loading model cost 0.006 seconds.
Prefix dict has been built succesfully.
Out[4]: ['干拌面']

In [5]: jieba2.lcut("干拌面")
Building prefix dict from /Users/slade/Desktop/B.txt ...
Dumping model to file cache /var/folders/hv/kfb7n4lj06590hqxjv6f3dd00000gn/T/jieba.uc4f38d90bf7ce748744ff94fb2863fe4.cache
Loading model cost 0.003 seconds.
Prefix dict has been built succesfully.
Out[5]: ['干拌', '面']

需要注意的是,去看Tokenizer源码,里面有这么一段读取调用:

    def gen_pfdict(self, f):
        lfreq = {}
        ltotal = 0
        f_name = resolve_filename(f)
        for lineno, line in enumerate(f, 1):
            try:
                line = line.strip().decode('utf-8')
                word, freq = line.split(' ')[:2]
                freq = int(freq)
                lfreq[word] = freq
                ltotal += freq
                for ch in xrange(len(word)):
                    wfrag = word[:ch + 1]
                    if wfrag not in lfreq:
                        lfreq[wfrag] = 0
            except ValueError:
                raise ValueError(
                    'invalid dictionary entry in %s at Line %s: %s' % (f_name, lineno, line))
        f.close()
        return lfreq, ltotal

在load_userdict的时候词库的词频可以省略不写,word, freq = line.split(' ')[:2]决定了这边需要加上,这个依赖于版本,我并没有实验不同版本。

A.txt:

干拌面 1

B.txt:

干拌 1
面 1

欢迎大家关注我的个人bolg知乎,更多代码内容欢迎follow我的个人Github,如果有任何算法、代码、转行疑问都欢迎通过邮箱发消息给我。

推荐阅读更多精彩内容

  • jieba分词,学习,为了全面了解该模块,,预设学习路线:官方文档——优秀博客文章——实践学习 官方文档部分 (文...
    竹林徒儿阅读 1,422评论 1 11
  • jieba “结巴”中文分词:做最好的 Python 中文分词组件"Jieba" (Chinese for "to...
    HappyCai阅读 36,848评论 6 35
  • 前言 从本文开始,我们进入实战部分。首先,我们按照中文自然语言处理流程的第一步获取语料,然后重点进行中文分词的学习...
    lanlantian123阅读 1,095评论 0 1
  • 参考:Python 中文分词组件 jiabaPython中文分词 jieba 十五分钟入门与进阶jieba完整文档...
    领悟悟悟悟阅读 1,551评论 1 1
  • 前言 从本文开始,我们进入实战部分。首先,我们按照中文自然语言处理流程的第一步获取语料,然后重点进行中文分词的学习...
    米饭超人阅读 13,291评论 1 17