Python中等同于Class.getResource()的是什么?
在Java中,如果我想读取一个包含我算法所需资源数据的文件,我该怎么做才能正确引用路径呢?
澄清一下,我想理解在Python的世界里,如何将数据和代码打包在一个模块里。
举个例子,我可能在写一些代码,目的是分析一个字符串,试图判断这个文本是用什么语言写的。为了实现这个功能,我需要一个包含语言模型数据的文件。
所以当我的代码被调用时,我希望能够加载一个(或多个)与模块一起打包的文件。我不太清楚在Python中该怎么做。
谢谢大家。
3 个回答
对于不太了解的Python爱好者来说,Java中的Class.getResource
的行为大致是这样的:提供的文件名(除非它已经是一个绝对路径)会根据类的包名转换成一个相对路径(因为类文件的目录路径通常和类的“包”声明是一致的)。然后,用于加载这个类的ClassLoader会根据自己的逻辑把这个路径字符串转换成一个URL对象,这个对象可以表示文件名、网络位置等。
Python和Java不一样,所以我们需要做一些近似处理,并理解提问者的意图。
Python的类并不明确地放在包里,虽然你可以通过把它们放在带有__init__.py
文件的文件夹中来创建包。
Python的标准库里没有类似URL
类的东西;虽然有很多支持连接互联网的功能,但通常你只需要用字符串来表示URL(和文件名),并适当地格式化它们。这可以说是一个错失的机会(虽然你可以自己写一个包装器,但可能会漏掉很多特殊情况和有用的功能)。总之,在Java的正常情况下,你并不指望通过这个过程得到一个网页URL。
Python有一个“工作目录”的概念,这个目录取决于Python进程是如何启动的。文件路径不一定是相对于“主类”(其实是“主模块”,因为Python不要求你把所有东西都放在一个类里)所在的目录。
所以你真正想要的,可能是获取与类对应的源文件的绝对路径。但这也不太可能实现。问题在于:给定一个类,你可以得到它来自的模块名,然后查找这个名字以获取实际的模块对象,再从模块对象中获取加载该模块时的文件名。然而,这个文件名是相对于模块加载时的工作目录的,而这个信息并没有被记录下来。如果工作目录在那之后发生了变化(通过os.chdir
),那就没办法了。
请尽量更清楚地说明你真正想要做的事情。
我觉得你在找的是 imp.load_source
这个东西:
import imp
module = imp.load_source('ModuleName', '/path/of/the/file.py')
module.FooBar()
我觉得你可能在找 pkgutil.get_data()
。它的说明是这样的:
pkgutil.get_data(package, resource)
从一个包中获取资源。
这个函数是 PEP 302 加载器的一个封装,用于获取数据。你需要提供一个包的名字,格式要像这样:foo.bar。资源的参数应该是相对文件名,用 / 作为路径分隔符。你不能使用父目录名 ..,也不能用以 / 开头的绝对路径。
这个函数会返回一个二进制字符串,也就是你指定的资源的内容。
对于已经在文件系统中导入的包,这个函数大致相当于:
d = os.path.dirname(sys.modules[package].__file__) data = open(os.path.join(d, resource), 'rb').read()
如果找不到这个包,或者无法加载,或者它使用的 PEP 302 加载器不支持 get_data(),那么就会返回 None。