我有一个python脚本,需要将一个大文件从磁盘加载到一个变量。这需要一段时间。该脚本将从另一个应用程序(仍然未知)多次调用,具有不同的选项,将使用stdout。是否有可能避免为脚本的每次调用读取大文件?
我想我可以在后台运行一个包含变量的大脚本。但是,如何用不同的选项调用脚本并从另一个应用程序中读取stdout?
答案 0 :(得分:3)
使其成为(Web)微服务:将所有不同的CLI参数形式化为HTTP端点,并从主应用程序向其发送请求。
答案 1 :(得分:1)
您可以将处理后的值存储在文件中,然后在另一个脚本中读取该文件中的值。
>>> import pickle as p
>>> mystr="foobar"
>>> p.dump(mystr,open('/tmp/t.txt','wb'))
>>> mystr2=p.load(open('/tmp/t.txt','rb'))
>>> mystr2
'foobar'
答案 2 :(得分:1)
(我误解了原来的问题,但我写的第一个答案有一个不同的解决方案,这可能对适合这种情况的人有用,所以我保持原样并提出第二个解决方案。 )
对于单台机器,操作系统提供的管道是您正在寻找的最佳解决方案。
基本上你将在python中创建一个永久运行的进程,它从管道中读取,并处理进入管道的命令,然后打印到sysout。
参考:http://kblin.blogspot.com/2012/05/playing-with-posix-pipes-in-python.html
来自上述来源
工作量 为了模拟我的工作量,我想出了一个名为pipetest.py的简单脚本,它接受输出文件名,然后将一些文本写入该文件。
#!/usr/bin/env python
import sys
def main():
pipename = sys.argv[1]
with open(pipename, 'w') as p:
p.write("Ceci n'est pas une pipe!\n")
if __name__ == "__main__":
main()
守则 在我的测试中,这个"文件"将是由我的包装器代码创建的FIFO。包装器代码的实现如下,我将在本文中进一步详细介绍代码:
#!/usr/bin/env python
import tempfile
import os
from os import path
import shutil
import subprocess
class TemporaryPipe(object):
def __init__(self, pipename="pipe"):
self.pipename = pipename
self.tempdir = None
def __enter__(self):
self.tempdir = tempfile.mkdtemp()
pipe_path = path.join(self.tempdir, self.pipename)
os.mkfifo(pipe_path)
return pipe_path
def __exit__(self, type, value, traceback):
if self.tempdir is not None:
shutil.rmtree(self.tempdir)
def call_helper():
with TemporaryPipe() as p:
script = "./pipetest.py"
subprocess.Popen(script + " " + p, shell=True)
with open(p, 'r') as r:
text = r.read()
return text.strip()
def main():
call_helper()
if __name__ == "__main__":
main()
答案 3 :(得分:1)
由于您已经可以将数据读入变量,因此您可以考虑使用mmap对文件进行内存映射。如果多个进程只读取它,这是安全的 - 支持编写器需要锁定协议。
假设你不熟悉内存映射对象,我会打赌你每天都使用它们 - 这就是操作系统加载和维护可执行文件的方式。基本上,您的文件将成为分页系统的一部分 - 尽管它不必采用任何特殊格式。
当您将文件读入内存时,它不太可能全部加载到RAM中,当“真正的”RAM变得过度订阅时,它将被分页。这种分页通常是一个相当大的开销。内存映射文件只是您的数据“就绪分页”。读入内存没有开销(虚拟内存,就是这样),只要你映射它就会存在。
当您尝试访问数据时,会发生页面错误并且子集(页面)被加载到RAM中 - 所有这些都由操作系统完成,程序员并不知道这一点。
当文件保持映射状态时,它会连接到分页系统。如果尚未进行更改,则映射同一文件的另一个进程将访问同一对象(请参阅MAP_SHARED
)。
它需要一个守护进程来保持内存中的内存映射对象是最新的,但除了创建链接到物理文件的对象之外,它不需要做任何其他操作 - 它可以休眠或等待关闭信号。
其他进程打开文件(使用os.open()
)并映射对象。
请参阅文档中的示例here以及Giving access to shared memory after child processes have already started