qrc资源文件供外部使用的方法

1 缘起

从入学之初就跟着师兄一起做一个PyQt5的项目,学到了很多东西。自从上次项目打包遇到资源文件处理难题之后,就开始慢慢在项目中引入Qt提供的qrc资源文件方案。

最近在系统地学PySide2(Qt for python的官方绑定),在其官方教程中有一个Data Visualization Tool Tutorial的数据可视化教程。在该教程中,用到了pandas库来读取一个本地csv文件。教程本身提供的是相对路径读取文件方法,但本人想使用qrc资源文件的方式来引入该csv文件,以培养习惯。不曾想,遇到了pandas无法读取csv文件的错误,在解决过程中对qrc资源文件的运作方式有了更深的理解。

2 问题重现

首先我的项目目录结构为

D:.
└─DataVisualization
    │  main.py
    │  
    ├─layouts
    │      main.ui
    │      
    └─resources
        │  all_day.csv
        │  data.qrc
        │  data_rc.py

data.qrc代码为

<RCC>
  <qresource prefix="data">
    <file>all_day.csv</file>
  </qresource>
</RCC>

在main.py中,按照正常的相对路径写法,能够正确打印csv文件内容,而使用qrc资源文件方法则不可行,具体代码为

import pandas as pd
from PySide2.QtCore import QFile, QIODevice

import DataVisualization.resources.data_rc

if __name__ == "__main__":
    data = pd.read_csv(":/data/all_day.csv")
    # data = pd.read_csv(r"DataVisualization\resources\all_day.csv")
    print(data)

运行此main.py报错FileNotFoundError,而使用注释内的语句则能够正常显示csv文件内容。

FileNotFoundError: [Errno 2] File b':/data/all_day.csv' does not exist: b':/data/all_day.csv'

3 解决方案

经过长时间的谷歌,终于从stack overflow找到了解决方案及原因。

总的来说,就是因为作为Qt内部使用的资源管理方案,只有Qt本身知道如何正确地从该资源文件中得到所需文件正确的路径并读取,而外界库甚至python自身也不能得到文件的具体路径。

既然外界读不到信息是因为找不到文件的具体路径,那么解决方案也就呼之欲出了:跳过路径,直接让Qt程序告诉第三方库所需文件的内容。

import io
import pandas as pd
from PySide2.QtCore import QFile, QIODevice

import DataVisualization.resources.data_rc

if __name__ == "__main__":
    file = QFile(":/data/all_day.csv")
    if file.open(QIODevice.ReadOnly):
        f = io.BytesIO(file.readAll().data())
        data = pd.read_csv(f)
        print(data)

值得注意的是,这里pandas.read_csv()通过此方案可行的原因是,read_csv()支持传入的参数既可以是文件路径也可以是buffer。对于其他某些接口可能必须要文件路径的则此路不通。

4 深入思考

4.1 qrc的原理

直接上结论:qrc文件本身类似于一个XML格式的文本,其记录了所包含的每一个文件的路径。关键在于,使用rcc/pyrcc5/pyside2-rcc对该文件进行编译时,程序遍历qrc文件里面的每一个文件路径,将该文件的二进制内容写入到相应的输出文件里。

例如,本文使用的all_day.csv文件是一个纯文本文件,其文件大小为56.4KB;包含该文件路径信息的data.qrc文件大小为85字节;通过pyside2-rcc.exe编译生成的data_rc.py文件大小为70.7KB。此外,当我编译完成了data_rc.py之后,即使我删除all_day.csv文件,程序照样能够正常运行并读取all_day.csv里面的数据。除了pyside2-rcc.exe将all_day.csv的所有信息统统写进了编译生成的data_rc.py这种解释外,我实在想不到为什么一个py文件能够达到70.7KB。

有了这样的结论,也就很好解释qrc文件的一些相关特性了,例如:

  1. 目标程序里所有内嵌的资源文件都是只读的,在程序运行时不能修改资源里的文件,只能读取使用。
  2. 当你修改了qrc资源文件包含的任意文件之后,你必须重复添加-编译的操作才能使更改生效。
  3. 除了Qt之外的程序想要直接从编译后的文件里面获取信息几乎是不可能的,必须要借助Qt内部接口读取资源文件信息。

4.2 qrc使用的其他注意事项

  1. 为了管理方便,需要编译进qrc资源文件的那些文件最好放在.qrc的所在文件夹或者其子文件夹内。

  2. 在不加前缀(prefix)的前提下,在程序中调用同级资源文件可以使用(":file_name")file = QFile(":/all_day.csv");调用子目录资源文件可以用(":path/to/file")file = QFile(":/resources/all_day.csv")

    在加前缀的情况下,在程序中调用同级资源文件可以使用(":/prefix/file_name")file = QFile(":/data/all_day.csv");调用子目录资源文件可以用(":/prefix/path/to/file")file = QFile(":/data/resources/all_day.csv")

  3. 对于文件大小超过4M的文件,不建议直接编译,而是使用选项-binary,具体文档看这里。另外,在Qt的python绑定中不支持-binary

5 总结

作为一个PySide2的入门者,我还有很多东西要学习,包括qrc也还有很多方面是一知半解的。如果对于qrc有什么好的见解,或者文章中有什么错误,希望能够多多交流。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,449评论 0 13
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,694评论 0 3
  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,841评论 0 5
  • Qt是属于一个跨平台的GUI开发软件,支持的平台有Unix、Linux、Windows/WinCE、IOS等。 Q...
    一叶之界阅读 8,156评论 0 17
  • 文/金银花 摘掉墨镜 我用蓝色的眼睛看天空 看天空以外的苍生 白云朵朵飞 青蛙也在朵朵飞 川流不息的人群 和接踵而...
    金银花开时阅读 168评论 0 0