在脚本调用之间保持Python变量

时间:2016-12-05 08:09:40

标签: python variables memory ipc ram

我有一个python脚本,需要将一个大文件从磁盘加载到一个变量。这需要一段时间。该脚本将从另一个应用程序(仍然未知)多次调用,具有不同的选项,将使用stdout。是否有可能避免为脚本的每次调用读取大文件?

我想我可以在后台运行一个包含变量的大脚本。但是,如何用不同的选项调用脚本并从另一个应用程序中读取stdout?

4 个答案:

答案 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