在脚本调用之间保留 Python 个变量

Keeping Python Variables between Script Calls

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

我想我可以在后台使用一个大型脚本 运行 来保存变量。但是,我怎样才能用不同的选项调用脚本并从另一个应用程序读取标准输出?

使其成为(网络)微服务:将所有不同的 CLI 参数形式化为 HTTP 端点,并从主应用程序向其发送请求。

您可以将处理后的值存储在一个文件中,然后在另一个脚本中从该文件中读取这些值。

>>> import pickle as p
>>> mystr="foobar"
>>> p.dump(mystr,open('/tmp/t.txt','wb'))
>>> mystr2=p.load(open('/tmp/t.txt','rb'))
>>> mystr2
'foobar'

(我误解了原来的问题,但我写的第一个答案有一个不同的解决方案,这可能对适合这种情况的人有用,所以我保持原样并提出第二个解决方案。 )

对于单台机器,OS 提供的管道是您所寻找的最佳解决方案。

本质上,您将在 python 中创建一个永远的 运行 进程,它从管道读取数据,处理进入管道的命令,然后打印到系统输出。

参考: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()

代码 在我的测试中,这个 "file" 将是由我的包装代码创建的 FIFO。 wrapper代码的实现如下,我会在下面详细介绍代码post:

#!/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()

既然已经可以将数据读入变量,那么可以考虑使用mmap对文件进行内存映射。如果多个进程只读取它,这是安全的 - 支持写入器需要锁定协议。

假设您不熟悉内存映射对象,我敢打赌您每天都在使用它们 - 这就是操作系统加载和维护可执行文件的方式。从本质上讲,您的文件成为分页系统的一部分 - 尽管它不必采用任何特殊格式。

当您将文件读入内存时,它不太可能全部加载到 RAM 中,当 "real" RAM 超额订阅时,它会被调出。这种分页通常是相当大的开销。内存映射文件就是您的数据 "ready paged"。读入内存(即虚拟内存)没有开销,一映射它就在那里。

当您尝试访问数据时,出现 页面错误 并且一个子集(页面)被加载到 RAM 中 - 所有这些都是由操作系统完成的,程序员没有意识到这一点.

虽然文件保持映射状态,但它已连接到分页系统。如果未进行更改,另一个映射同一文件的进程将访问同一对象(参见 MAP_SHARED)。

它需要一个守护进程来保持内存映射对象在内核中的当前状态,但除了创建链接到物理文件的对象之外,它不需要做任何其他事情——它可以休眠或等待关闭信号。

其他进程打开文件(使用os.open())并映射对象。

查看文档中的示例,here and also Giving access to shared memory after child processes have already started