0

I have a text file, params.txt say, that is of the following form (ignore the colour formatting, this is a plain text file not python code):

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]

i.e. the variables are separated by their values by =, the values are a mixture of ints, floats, and scientific notation, there are sometimes two variable/value pairs on a line separated by a single space, and there are headings of the form

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

In python, how do I read the text file, and automatically in my python script create the same variables and assign them the same values as are in the file?

The format of the file will be identical each time so brute forcing would be possible but I'm sure there's an elegant python/regex solution (but I'm new to python and have barely ever regexed!)

martineau
  • 119,623
  • 25
  • 170
  • 301
jms547
  • 201
  • 3
  • 11

5 Answers5

1

now if you want to (hardcode?) data in .txt file to .py file you should use something like this:

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))

this will create a new python file named sets.py (you can change name) and store all values from text file to .py file. Now to use these values first make sure that sets.py is in the same directory as your main python scipt and then do from sets import * now you will be able to acces any of those values by just typing its name and it will be recognized. try it out

Matiiss
  • 5,970
  • 2
  • 12
  • 29
0

you should probably not store it this way would be my advice.

If it isnt even considered for humans to read use pickle to store python objects.

If it is supposed to be readable/editable to humans i would suggest csv files or something in that nature

  • I can't change the format of the text files: they're written by code that in principle I don't have access to. – jms547 Oct 28 '20 at 20:12
0

This should be doable with dictionary's I think.

something like this:

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

this leaves an output in the form of a dictionary with as key: the variable name and with the value: the variable itself. Like this:

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

I do not know a way of implementing some way of detecting if it is an int or float...

0

improved script of one of the answers that can detect int, float and 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
Matiiss
  • 5,970
  • 2
  • 12
  • 29
  • Thanks, this certainly works. But I would suit my subsequent workflow better to have just the values stored in the appropriate variables and not a dictionary of key/value pairs. Do you know if this is possible? – jms547 Oct 28 '20 at 20:34
  • @jms547 so you want to add those values to .py file like this: (example) `Lx = 512` (hardcode?) – Matiiss Oct 28 '20 at 20:37
  • yeah, I want to have Lx = 512 etc ready to use just as variables later on in the script, rather than access the value by using variables['Lx']. Maybe I could just hard-code them in once all the values are in the dictionary, but I'm sure there's a more elegant solution! – jms547 Oct 28 '20 at 20:52
  • @jms547 I just added a new answer so check it out, it has the solution – Matiiss Oct 28 '20 at 20:56
0

For future readers, another solution is to use exec() to run the appropriately chopped-up strings from params.txt as code, to assign the variables with the values given:

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])

This avoids having to parse the file, create a dictionary, print out a .py file and then reading in the .py file, as per Matiiss's solution.

I have posted another question here asking whether or not this is actually a good idea. EDIT: it's not a great idea as exec() is a security risk, but probably ok in code that's only ever run locally and does not face the outside world. In particular if nobody can ever write malicious code in params.txt that exec() would then execute.

jms547
  • 201
  • 3
  • 11