【问题标题】:Read values from a file, automatically creating variables to store them从文件中读取值,自动创建变量来存储它们
【发布时间】:2020-10-28 19:46:43
【问题描述】:

我有一个文本文件,params.txt,格式如下(忽略颜色格式,这是一个纯文本文件,不是 python 代码):

Lx = 512 Ly = 512
g = 400
================ Dissipation =====================
nupower = 8 nu = 0
alphapower = -0 alpha = 0
================ Timestepping =========================
SOMEFLAG = 1
SOMEOTHERFLAG = 4
dt = 2e-05
[...and so on]

即变量由它们的值通过= 分隔,值是整数、浮点数和科学记数法的混合,有时一行中有两个变量/值对,由一个空格分隔,并且有表格的标题

================ HeadingToBeDiscarded ================

在 python 中,我如何读取文本文件,并在我的 python 脚本中自动创建相同的变量并为它们分配与文件中相同的值?

文件的格式每次都是相同的,所以暴力破解是可能的,但我确信有一个优雅的 python/正则表达式解决方案(但我是 python 新手,几乎没有正则表达式!)

【问题讨论】:

  • {k:v for k,v in re.findall(r"(\w+)\s*=(?!==)\s*([\S]+)", file_content)}
  • Wiktor,我该如何开始解析它以了解它应该如何工作?!

标签: python string file-management


【解决方案1】:

现在如果你想(硬编码?).txt 文件中的数据到.py 文件,你应该使用这样的东西:

temp_list = []
with open("params.txt") as file:
    while True:
        line = file.readline()
        line = line.strip()
        value = line.split(' ')
        for i, word in enumerate(value):
            if word == '=':
                var = f'{value[i-1]} = {value[i+1]}'
                temp_list.append(var)
        if not line:
            break

with open('sets.py', 'w') as f:
    f.write('\n'.join(temp_list))

这将创建一个名为 sets.py 的新 python 文件(您可以更改名称)并将所有值从文本文件存储到 .py 文件。现在要使用这些值,首先确保sets.py 与您的主要python scipt 位于同一目录中,然后执行from sets import * 现在您只需输入其名称即可访问这些值中的任何一个,它将被识别。试试看

【讨论】:

    【解决方案2】:

    我的建议是,您可能不应该以这种方式存储它。

    如果甚至不考虑人类阅读,请使用 pickle 来存储 python 对象。

    如果它应该对人类可读/可编辑,我会建议使用 csv 文件或类似的东西

    【讨论】:

    • 我无法更改文本文件的格式:它们是由原则上我无权访问的代码编写的。
    【解决方案3】:

    我认为这应该可以用字典来实现。

    类似这样的:

    def getVariables():
    with open("filename.txt",'r') as file:
        variables = {}
        while True:
            line = file.readline()
            line = line.strip()
            value = line.split(' ')
            for i, word in enumerate(value):
                if word == '=':
                    variables[str(value[i-1])] = value[i+1]
            if not line:
                break
    return variables
    

    这会以字典的形式留下一个输出,其中键:变量名,值:变量本身。像这样:

    变量 = {'Lx' : '512', 'Ly' : '512', 'nupower' : '8', 'nu' : '0'}

    我不知道如何实现某种方法来检测它是 int 还是 float...

    【讨论】:

    • 你可以看看我的答案(我用过你的并改进了它)
    【解决方案4】:

    改进了可以检测 int、float 和 str 的答案之一的脚本

    def getVariables():
        with open("params.txt") as file:
            variables = {}
            while True:
                line = file.readline()
                line = line.strip()
                value = line.split(' ')
                for i, word in enumerate(value):
                    if word == '=':
                        try:
                            variables[str(value[i-1])] = int(value[i+1])
                        except ValueError:
                            try:
                                variables[str(value[i-1])] = float(value[i+1])
                            except ValueError:
                                variables[str(value[i-1])] = (value[i+1])
                if not line:
                    break
        return variables
    

    【讨论】:

    • 谢谢,这确实有效。但我会更好地适应我的后续工作流程,将值存储在适当的变量中,而不是键/值对的字典。你知道这是否可能吗?
    • @jms547 所以你想像这样将这些值添加到 .py 文件中:(示例)Lx = 512(硬代码?)
    • 是的,我想让 Lx = 512 等准备好稍后在脚本中用作变量,而不是通过使用变量 ['Lx'] 访问值。一旦所有值都在字典中,也许我可以对它们进行硬编码,但我确信有一个更优雅的解决方案!
    • @jms547 我刚刚添加了一个新答案,请检查一下,它有解决方案
    【解决方案5】:

    对于未来的读者,另一种解决方案是使用exec()params.txt 中适当切分的字符串作为代码运行,以给定值分配变量:

    with open('params.txt', 'r') as infile:
    for line in infile:
        splitline = line.strip().split(' ')
        for i, word in enumerate(splitline):
            if word == '=':
                # DANGER! Don't use this unless you completely trust the content of params.txt!
                exec(splitline[i-1] + splitline[i] + splitline[i+1])
    

    这避免了按照 Matiiss 的解决方案解析文件、创建字典、打印出 .py 文件然后读取 .py 文件。

    I have posted another question here 询问这是否真的是一个好主意。 编辑:这不是一个好主意,因为exec() 存在安全风险,但在只在本地运行且不面向外部世界的代码中可能还可以。特别是如果没有人可以在params.txt 中编写恶意代码,exec() 会执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      • 2015-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多