python实战项目词云生成器(wordcloud+jieba+pyinstaller打包)——词云生成软件【Pyinstaller打包问题解决】

本文介绍了一个使用Python的jieba和wordcloud库实现的文章词云图生成器,具备交互界面,能在无Python环境下运行。文章详细描述了代码实现过程,包括界面设计、文件读取、词云生成及pyinstaller打包技巧。

最近学习了python的jieba分词库和wordcloud词云库,诞生了想写个小demo,使用python实现文章的词云图的绘制,然后需要具有交互界面,并且能够在没有python环境的电脑下运行,方便不懂编程的人直接使用。

全部代码实现的打包exe文件:WordCloudTool免安装版

主要使用的库和软件如下:

python3.7.1  实现算法编程语言
jieba 词语分割
wordcloud 绘制云图
matplotlib.pyplot 显示/保存云图
注意,默认上述环境和库以安装完毕!
 

界面结构设计

登录界面如下:

注册页面如下:

文件选择页面如下:

 

完整代码如下:

#_*_coding:utf-8_*_
from tkinter import filedialog
import tkinter as tk
import jieba
import tkinter.messagebox
import pickle
import wordcloud
import matplotlib

#创建一个窗体
window = tk.Tk() #建立以个窗口
window.title("词云生成器") #命名窗体
window.geometry('450x300') #设置窗体大小
window.resizable(False, False)

# welcome image
canvas = tk.Canvas(window, height=300, width=450)
image_file = tk.PhotoImage(file='bg.gif')
image = canvas.create_image(0,0, anchor='nw', image=image_file)
canvas.pack(side=tk.LEFT)

# user information
#tk.Label(window, text='User name: ').place(x=50, y= 150)
#tk.Label(window, text='Password: ').place(x=50, y= 190)

var_usr_name = tk.StringVar()
var_usr_name.set('example@python.com')
entry_usr_name = tk.Entry(window, textvariable=var_usr_name)
entry_usr_name.place(x=160, y=150)
var_usr_pwd = tk.StringVar()
entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, show='*')
entry_usr_pwd.place(x=160, y=190)


def wordclounds_w():
    def Open_file():
        try:
            filename = filedialog.askopenfilename( \
                initialdir='C:', title="Please select txt file", \
                filetypes=(("txt文件", "*.txt"), ("所有文件", "*.*")))
        except FileNotFoundError:
            pass
        f = open(filename, "r", encoding="utf-8")
        t = f.read()
        f.close()
        ls = jieba.lcut(t)
        txt = " ".join(ls)
        w = wordcloud.WordCloud(font_path="msyh.ttf", width=1000, height=700, background_color="white", max_words=15)
        w.generate(txt)
        #以文件名输出为.png图片
        lists = list(reversed(filename))
        for i in range(len(lists)):
            if lists[i] == "/":
                break
        w.to_file("".join(reversed(lists[4:i]))+".png")

    window_w = tk.Toplevel(window)
    window_w.geometry('450x300')
    window_w.title('select file window')
    window_w.resizable(False, False)

    # txt introduction
    # welcome image
    canvas = tk.Canvas(window_w, height=300, width=450)
    image_files = tk.PhotoImage(file='slg.gif')
    images = canvas.create_image(0, 0, anchor='nw', image=image_files)
    canvas.pack(side=tk.LEFT)

    btn_confirm_sign_up = tk.Button(window_w, text='Please open the txt file!', command=Open_file)
    btn_confirm_sign_up.place(x=130, y=200)
    window_w.mainloop()

#usr_login
def usr_login():
    usr_name = var_usr_name.get()
    usr_pwd = var_usr_pwd.get()
    try:
        with open('usrs_info.pickle', 'rb') as usr_file:
            usrs_info = pickle.load(usr_file)
    except FileNotFoundError:
        with open('usrs_info.pickle', 'wb') as usr_file:
            usrs_info = {'admin': 'admin'}
            pickle.dump(usrs_info, usr_file)
    if usr_name in usrs_info:
        if usr_pwd == usrs_info[usr_name]:
            tk.messagebox.showinfo(title='Welcome', message='Welcome use this tool! ' + usr_name)
            wordclounds_w()
        else:
            tk.messagebox.showerror(message='Error, your password is wrong, try again.')
    else:
        is_sign_up = tk.messagebox.askyesno('Welcome',
                                            'You have not sign up yet. Sign up today?')
        if is_sign_up:
            usr_sign_up()

#usr_sign_up
def usr_sign_up():
    def sign_to_Mofan_Python():
        np = new_pwd.get()
        npf = new_pwd_confirm.get()
        nn = new_name.get()
        with open('usrs_info.pickle', 'rb') as usr_file:
            exist_usr_info = pickle.load(usr_file)
        if np != npf:
            tk.messagebox.showerror('Error', 'Password and confirm password must be the same!')
        elif nn in exist_usr_info:
            tk.messagebox.showerror('Error', 'The user has already signed up!')
        else:
            exist_usr_info[nn] = np
            with open('usrs_info.pickle', 'wb') as usr_file:
                pickle.dump(exist_usr_info, usr_file)
            tk.messagebox.showinfo('Welcome', 'You have successfully signed up!')
            window_sign_up.destroy()

    window_sign_up = tk.Toplevel(window)
    window_sign_up.geometry('350x200')
    window_sign_up.title('Sign up window')
    window_sign_up.resizable(False, False)


    new_name = tk.StringVar()
    new_name.set('example@python.com')
    tk.Label(window_sign_up, text='User name: ').place(x=10, y=10)
    entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
    entry_new_name.place(x=150, y=10)

    new_pwd = tk.StringVar()
    tk.Label(window_sign_up, text='Password: ').place(x=10, y=50)
    entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
    entry_usr_pwd.place(x=150, y=50)

    new_pwd_confirm = tk.StringVar()
    tk.Label(window_sign_up, text='Confirm password: ').place(x=10, y=90)
    entry_usr_pwd_confirm = tk.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*')
    entry_usr_pwd_confirm.place(x=150, y=90)

    btn_confirm_sign_up = tk.Button(window_sign_up, text='Sign up', command=sign_to_Mofan_Python)
    btn_confirm_sign_up.place(x=150, y=130)



# login and sign up button
btn_login = tk.Button(window, text='Login', command=usr_login)
btn_login.place(x=170, y=230)
btn_sign_up = tk.Button(window, text='Sign up', command=usr_sign_up)
btn_sign_up.place(x=270, y=230)

window.mainloop()

pyinstaller打包问题处理

问题主要是针对pyinstaller对jiebawordcloud库打包时出现的问题。

【打包jieba库时,因提前处理了路径问题,在此没有出现错误!下面仅为jieba库相关问题处理案例!】

1. No such or directory: u’C:\user\LOOP\AppData\Local\Temp\_MEI12~1\jieba\dict.txt’

这是用于jieba中调用了dict.txt文件,而pyinstaller在打包时不会自动把该文件打包,定位到出现错误的文件Lib\site-packages\jieba\_compat.py的8行,可以看到如下:

try:
    import pkg_resources
    get_module_res = lambda *res: pkg_resources.resource_stream(__name__,
                                                                os.path.join(*res))
except ImportError:
    get_module_res = lambda *res: open(os.path.normpath(os.path.join(
                            os.getcwd(), os.path.dirname(__file__), *res)), 'rb')


该方法就是在当前文件 (_compat.py) 目录作为get_module_res的目录,在pyinstaller manual文档中解释如下: 

也就是说使用__file__的相对路径在打包完成后会变成绝对路径,并且以_MEIxxxxx文件名存储在缓存文件夹中。并且也给出解决方案,可以使用sys.executable也就是当前的运行目录,就是运行打包好的exe文件目录,如果是在使用python时,就是调用的python路径。

因此,解决方法如下:

try:
    import pkg_resources
    get_module_res = lambda *res: open(os.path.normpath(os.path.join(
        os.getcwd(), os.path.dirname(sys.executable), *res)), 'rb')

except ImportError:
    get_module_res = lambda *res: open(os.path.normpath(os.path.join(
                            os.getcwd(), os.path.dirname(__file__), *res)), 'rb')

同理,在打包wordcloud也会出现相似的问题,定位到相关文件(Lib\site-packages\wordcloud\wordcloud.py)第28、29、30行上下:

FONT_PATH = os.environ.get("FONT_PATH", os.path.join(os.path.dirname(__file__),
                                                     "DroidSansMono.ttf"))
STOPWORDS = set([x.strip() for x in open(
    os.path.join(os.path.dirname(__file__), 'stopwords')).read().split('\n')])

很明显是__file__问题,修改如下:

FONT_PATH = os.environ.get("FONT_PATH", os.path.join(os.path.dirname(sys.executable),
                                                     "DroidSansMono.ttf"))
STOPWORDS = set([x.strip() for x in open(
    os.path.join(os.path.dirname(sys.executable), 'stopwords')).read().split('\n')])

注意:以上修改只是针对使用pyinstaller打包时,因为改变了其文件路径,在调试和运行时会出错

最后把dict.txtstopwords以及img文件拷贝到与生成的.exe文件同一目录即可。

Successfully:

一个基于 Python 实现的“交互式生成器”,支持用户输入任意中文或英文文本,自动完成分、过滤停用、统计频并生成可视化图。 一、项目主要特点包括: 1.中文分与停用过滤:使用 `jieba` 对输入文本进行分,结合内置的常见停用表,剔除长度小于 2 或无意义字符,确保结果更加准确清晰。 2.多平台中文字体兼容:自动检测当前操作系统(Windows、macOS、Linux)可用的中文字体路径,配置 `matplotlib` 渲染中文,避免乱码问题。 3.灵活的配置:可自定义的标题、配色方案(colormap)、背景色、最大数等参数;生成完成后可直接预览并可选保存为 PNG/JPG 文件。 二、图形界面与命令行两种交互方式: 1.Tkinter GUI:提供一个简洁直观的窗口界面,用户可以在多行文本框中输入或粘贴文本,设置参数后点击“生成”按钮即可实时查看结果,并可一键加载文本文件、保存图、清空输入。 2.命令行模式:通过终端提示进行文本输入、文件加载或使用示例文本,支持自定义标题与输出文件名,适合不习惯图形界面或在服务器环境下使用。 3.轻量易集成的快速调用:此外还封装了 `quick_generate(text, title)` 函数,便于在其他脚本或项目中直接生成,快速完成批量可视化需求。 总之,本项目兼顾了易用性与可定制性,既适合对效果有个性化需求的普通用户,也方便开发者将其集成到更复杂的数据分析或报告流程中。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值