临时文件是计算机程序存储临时数据的文件, 它的扩展名通常是 ".temp". 本文用于记录使用 Python 提供的临时文件 API 解决实际问题的过程, 主要内容包括问题描述, tempfile 库简要介绍, 解决方案等.
问题描述
tempfile 库
解决方案
总结
参考材料
问题描述
一些开源工具提供的接口有时不能满足特定场景下的需求, 需要根据实际情况进行调整. 比如基于 Java 的自动文摘工具 PKUSUMSUM, 它接收一篇文章作为输入, 输出文章的摘要, 要求输入输出都是磁盘上的文件:
java -jar PKUSUMSUM.jar -T 1 -input [输入文件] -output [输出文件] -L 2 -n 15 -m 5 -stop n
由于我的代码是用 Python 写的, 需要进行摘要抽取的文章已经加载到内存了, 并且通过工具生成摘要以后需要马上进行评测, 自动文摘工具 PKUSUMSUM 提供的接口没办法直接满足我的需求. Python 脚本怎样调用 Jar 包? 内存中的文章怎样作为 PKUSUMSUM 的输入? PKUSUMSUM 输出的摘要怎样读入到内存中?
tempfile 库
通过查阅资料, 我了解到 Python 标准库中有名字叫 tempfile 的模块, 这个模块实现了创建临时文件和文件夹的功能, 相关接口包括:
TemporaryFile: 创建临时文件, 一旦文件关闭, 就立即被销毁;
NamedTemporaryFile: 创建有名字的, 在文件系统中可见的临时文件, 可以通过指定 delete 参数设置文件关闭时的行为;
TemporaryDirectory: 创建临时文件夹;
mkstemp(): 创建临时文件, 需要手动关闭和销毁;
mkdtemp(): 创建临时文件夹, 需要手动关闭和销毁.
其中 14 实现了上下文管理器协议 (实现了 `__enter__` 和 `__exit__` 两个特殊方法), 配合 `with` 关键字使用, 可以方便地自动关闭文件; 56 是低阶 API, 使用完临时文件或文件夹以后, 需要手动关闭.
- import tempfile # # 导入模块
- from pathlib import Path
- fin = tempfile.TemporaryFile(mode='w', encoding='utf8') # 创建临时文件
- fin.name # C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmpi1ozv3mj
- Path(fin.name).exists() # True, 临时文件是存在的
- fin.delete # True,delete 参数的默认值是 True, 表示文件关闭以后, 立即销毁
- with fin.file as fp: # 上下文管理器自动关闭文件
- content = bytes('The quick brown fox jumps over the lazy dog', 'utf8')
- fp.write(content)
- Path(fin.name).exists() # False, 临时文件已经被销毁
解决方案
回到我们的问题:
Python 脚本怎样调用 Jar 包?
我们可以使用 os 模块的 system 方法执行 Shell 命令, 调用 Jar 包:
os.system(f'java -jar PKUSUMSUM.jar -T 1 -input {fin.name} -output {fout.name} -L 2 -n 15 -m {algo_id} -stop n')
内存中的文章怎样作为 PKUSUMSUM 的输入?
我们可以首先把文章写入到临时文件中, 然后通过引用临时文件的 name 属性, 就可以把文章当成本地文件那样使用了:
- # 把文章写入到临时文件中
- fin = tempfile.NamedTemporaryFile(delete=False)
- fin.close()
- with open(Path(fin.name), mode='w', encoding='utf8') as fp:
- fp.write(text)
注意临时文件必须要先关闭, 然后才能往文件里面中写内容, 否则会触发 Permission denied 异常.
PKUSUMSUM 输出的摘要怎样读入到内存中?
思路与第二个问题一样, 创建临时文件并通过 name 属性进行引用, 临时文件销毁前读出里面的内容 (就是 PKUSUMSUM 抽取出的摘要).
完整的代码如下:
- def do_extractive_summarization(text: str, algo: str = 'TextRank') -> str:
- """基于 PKUSUMSUM 实现抽取式摘要算法"""
- algo_warehouse = {'Centroid': 2, 'ILP': 3, 'LexPageRank': 4, 'TextRank': 5, 'Submodular': 6}
- if algo not in algo_warehouse:
- raise ValueError(f'Invalid extractive summarization algorithm: {algo}')
- algo_id = algo_warehouse[algo]
- # 把文章写入到临时文件中
- fin = tempfile.NamedTemporaryFile(delete=False)
- fin.close()
- with open(Path(fin.name), mode='w', encoding='utf8') as fp:
- fp.write(text)
- # 运行 PKUSUMSUM.jar, 把生成的摘要写入到临时文件中
- fout = tempfile.NamedTemporaryFile(delete=False)
- fout.close()
- os.system(f'java -jar PKUSUMSUM.jar -T 1 -input {fin.name} -output {fout.name} -L 2 -n 15 -m {algo_id} -stop n')
- with open(Path(fout.name), mode='r', encoding='utf8') as fp:
- content = fp.read()
- summary = ' '.join(word_tokenize(content))
- Path(fin.name).unlink()
- Path(fout.name).unlink()
- return summary
总结
Python 的 tempfile 模块提供了方便的创建临时文件和文件夹的接口, 这些接口配合在 Python 脚本中执行 Shell 命令的方法一起使用, 可以在开源工具和自己的代码之间创建一个 "适配层"(我在写些什么? 我怎么自己都看不懂?);PKUSUMSUM 实现了多种抽取式摘要算法, 是自动文摘研究的利器.
参考材料
- tempfile - Generate temporary files and directories https://docs.python.org/3/library/tempfile.html
- https://github.com/PKULCWM/PKUSUMSUM
tempfile 模块报错: PermissionError: Errno 13 Permission denied 的解决方法
Python 之将字符串转换为字节的两种方法 https://www.cnblogs.com/Jony-2018/p/10800082.html
Python 调用 shell 命令常用方法 https://www.cnblogs.com/pengpp/p/9833349.html
来源: http://www.bubuko.com/infodetail-3784838.html