Python 使用函数将多个变量写入文件

Python 使用函数将多个变量写入文件,python,Python,我正在编写一个函数,将变量作为字典导出到外部文件。 从另一个脚本调用该函数时会出现问题。我认为这与globals参数有关 import sys import os mydict = {} #'initialising" the an empty dictionary to be used locally in the function below def writeToValues(name): fileName = os.path.splitext(os.path.basenam

我正在编写一个函数,将变量作为字典导出到外部文件。 从另一个脚本调用该函数时会出现问题。我认为这与globals参数有关

import sys
import os

mydict = {}  #'initialising" the an empty dictionary to be used locally in the function below

def writeToValues(name):
    fileName = os.path.splitext(os.path.basename(sys.argv[0]))[0]
    valuePrint=open("values.py","a")
    def namestr(obj,namespace):
        return[name for name in namespace if namespace[name] is obj]
    b = namestr(name, globals())
    c = "".join(str(x) for x in b)
    mydict[(c)] = name
    valuePrint.write(fileName)
    valuePrint.write("=")
    valuePrint.write(str(mydict))
    valuePrint.write("\n")
    valuePrint.close()
    return mydict

a = 2
b = 3

writeToValues(a)
writeToValues(b)
我得到以下结果:

主Junkfile={'a':2'b':3} 注意,单词Main Junkfile是我运行的脚本的名称,因为函数首先要做的就是获取文件名并用它命名字典

现在请帮助我,因为如果我从另一个脚本导入函数,则无法生成相同的函数。 另一个问题是,运行脚本两次会分步生成值

主Junkfile={'a':2} 主Junkfile={b':3,'a':2}
我无法将文件打开模式从“附加”更改为“写入”,因为我也想存储来自其他脚本的值。

这并不完美,但作为一个示例可能会有所帮助:

import sys
import os

mydict = {}
def namestr(obj,namespace):
    return[name for name in namespace if namespace[name] is obj]

def writeto(name):
    fout = 'values.py'
    filename = os.path.splitext(os.path.basename(sys.argv[0]))[0]
    with open (fout, 'a') as f:
        b = namestr(name, globals())
        c = "".join(str(x) for x in b)
        mydict[(c)] = name
        data = filename + '=' + str(mydict) + '\n'
        f.write(data)
    return mydict

a = 2
b = 3

if __name__ == '__main__':
    writeto(a)
    writeto(b)

首先,要获取当前正在执行的脚本名,或者更确切地说是调用函数的模块名,您必须从堆栈跟踪中获取它。全局变量也是如此——它将在writeToValues函数的相同上下文中执行,因此不会从“调用者”中拾取全局变量。要解决此问题,您可以使用inspect模块:

这将确保您获得导入脚本并在其中调用writeToValues的模块的名称

请记住,如果您打算编写可用的Python文件,这是一个非常糟糕的主意-如果您的脚本名有空格(如示例中所示),它将用空格编写变量名,如果您尝试将结果文件加载到Python解释器中,这将进一步导致语法错误

第二,为什么您要以fluffy的名义进行反向查找以查找变量名?您知道:

a = 2
b = 2
ab = 5

writeToValues(b)
将写入{ab:2},而不是{b:2}使其在意图上不正确会保存错误的var,在状态表示中也会保存错误的值,对吗?您应该传递一个要存储/更新的变量名,以确保选择了正确的属性

更新部分的问题更大——您需要更新文件,而不仅仅是附加到文件中。这意味着您需要找到当前脚本的行,删除它,然后用相同的名称编写一个新的dict。如果您不希望您的文件增长到很大的比例,也就是说,您可以将其部分存储在工作记忆中,您可以通过以下方式实现:

import os
import inspect

def writeToValues(name):
    caller = inspect.getmodule(inspect.stack()[1][0])
    caller_globals = caller.__dict__  # use this instead of globals()
    caller_name = os.path.splitext(os.path.basename(caller.__file__))[0]
    # keep 'mydict' list in the caller space so multiple callers can use this
    target_dict = caller_globals['mydict'] = caller_globals.get('mydict', {})
    if name not in caller_globals:  # the updated value no longer exists, remove it
        target_dict.pop(name, None)
    else:
        target_dict[name] = caller_globals[name]
    # update the 'values.py':
    # optionaly check if you should update - if values didn't change no need for slow I/O
    with open("values.py", "a+") as f:
        last_pos = 0  # keep the last non-update position
        while True:
            line = f.readline()  # we need to use readline() for tell() accuracy
            if not line or line.startswith(caller_name):  # break at the matching line or EOF
                break
            last_pos = f.tell()  # new non-update position
        append_data = f.readlines()  # store in memory the rest of the file content, if any
        f.seek(last_pos)  # rewind to the last non-update position
        f.truncate()  # truncate the rest of the file
        f.write("".join((caller_name, " = ", str(target_dict), "\n")))  # write updated dict
        if append_data:  # write back the rest of the file, if truncated
            f.writelines(append_data)
    return target_dict
否则,请使用临时文件在读取时写入所有内容(与当前脚本匹配的行除外),为当前脚本追加新值,删除原始值,并将临时文件重命名为values.py

现在,如果您将上述内容存储在value_writer.py中,并在脚本my_script.py中使用它,如下所示:

对于您将其导入到的任何脚本,也应该如此。现在,让多个脚本在没有锁定机制的情况下编辑同一个文件是一个即将发生的意外,但这完全是另一回事


此外,如果您的值很复杂,系统将中断,或者更确切地说,您的dict打印输出看起来不正常。帮你自己一个忙,使用一些适当的序列化,即使是可怕的pickle也比这个好。

如果另一个脚本也是python,那么你缺少了典型的:if name==main:construction imports文件名创建可能无法按预期工作,然后使用os.path将当前目录更改为你想要的目录,以上回答了我所有的问题。您是对的,值文件呈指数增长,因为它附加而不是替换。当值相同时,反向查找也会出错。我试图避免pickle或sqlite3数据库。是否有更好的方法导出要在另一个脚本中使用的变量?主要是在数学环境中,我将在不同的文件中使用变量值进行多个计算并更新它们。我是一个完全的编程新手,你将如何序列化数据以便在脚本之间共享取决于数据-在纯Python中,如果你只有数字列表存储文件中的数字,.join你的数字,然后通过读取文件并执行你的数字来检索它=[floatnum for num in file_content.split,]应该足够了。对于更复杂的结构,您可以使用JSON——它速度足够快,并且本身可以发挥大部分“魔力”。如果您想将numpy依赖项添加到您的项目中,它有一些非常快速的文件存储和检索方法,所以一定要查看它。
import os
import inspect

def writeToValues(name):
    caller = inspect.getmodule(inspect.stack()[1][0])
    caller_globals = caller.__dict__  # use this instead of globals()
    caller_name = os.path.splitext(os.path.basename(caller.__file__))[0]
    # keep 'mydict' list in the caller space so multiple callers can use this
    target_dict = caller_globals['mydict'] = caller_globals.get('mydict', {})
    if name not in caller_globals:  # the updated value no longer exists, remove it
        target_dict.pop(name, None)
    else:
        target_dict[name] = caller_globals[name]
    # update the 'values.py':
    # optionaly check if you should update - if values didn't change no need for slow I/O
    with open("values.py", "a+") as f:
        last_pos = 0  # keep the last non-update position
        while True:
            line = f.readline()  # we need to use readline() for tell() accuracy
            if not line or line.startswith(caller_name):  # break at the matching line or EOF
                break
            last_pos = f.tell()  # new non-update position
        append_data = f.readlines()  # store in memory the rest of the file content, if any
        f.seek(last_pos)  # rewind to the last non-update position
        f.truncate()  # truncate the rest of the file
        f.write("".join((caller_name, " = ", str(target_dict), "\n")))  # write updated dict
        if append_data:  # write back the rest of the file, if truncated
            f.writelines(append_data)
    return target_dict
import value_writter

a = 2
b = 3

value_writter.write_to_values("a")
value_writter.write_to_values("b")

a = 5

value_writter.write_to_values("a")

# values.py contains: my_script = {"a": 5, "b": 3}