[python] Write variable to file, including name

Let's say I have the following dictionary in a small application.

dict = {'one': 1, 'two': 2}

What if I would like to write the exact code line, with the dict name and all, to a file. Is there a function in python that let me do it? Or do I have to convert it to a string first? Not a problem to convert it, but maybe there is an easier way.

I do not need a way to convert it to a string, that I can do. But if there is a built in function that does this for me, I would like to know.

To make it clear, what I would like to write to the file is:

write_to_file("dict = {'one': 1, 'two': 2}")

This question is related to python

The answer is


The default string representation for a dictionary seems to be just right:

>>> a={3: 'foo', 17: 'bar' }
>>> a
{17: 'bar', 3: 'foo'}
>>> print a
{17: 'bar', 3: 'foo'}
>>> print "a=", a
a= {17: 'bar', 3: 'foo'}

Not sure if you can get at the "variable name", since variables in Python are just labels for values. See this question.


Do you just want to know how to write a line to a file? First, you need to open the file:

f = open("filename.txt", 'w')

Then, you need to write the string to the file:

f.write("dict = {'one': 1, 'two': 2}" + '\n')

You can repeat this for each line (the +'\n' adds a newline if you want it).

Finally, you need to close the file:

f.close()

You can also be slightly more clever and use with:

with open("filename.txt", 'w') as f:
   f.write("dict = {'one': 1, 'two': 2}" + '\n')
   ### repeat for all desired lines

This will automatically close the file, even if exceptions are raised.

But I suspect this is not what you are asking...


I found an easy way to get the dictionary value, and its name as well! I'm not sure yet about reading it back, I'm going to continue to do research and see if I can figure that out.

Here is the code:

your_dict = {'one': 1, 'two': 2}

variables = [var for var in dir() if var[0:2] != "__" and var[-1:-2] != "__"]

file = open("your_file","w")
for var in variables:
     if isinstance(locals()[var], dict):
          file.write(str(var) + " = " + str(locals()[var]) + "\n")
file.close()

Only problem here is this will output every dictionary in your namespace to the file, maybe you can sort them out by values? locals()[var] == your_dict for reference.

You can also remove if isinstance(locals()[var], dict): to output EVERY variable in your namespace, regardless of type. Your output looks exactly like your decleration your_dict = {'one': 1, 'two': 2}.

Hopefully this gets you one step closer! I'll make an edit if I can figure out how to read them back into the namespace :)

---EDIT---

Got it! I've added a few variables (and variable types) for proof of concept. Here is what my "testfile.txt" looks like:

string_test = Hello World
integer_test = 42
your_dict = {'one': 1, 'two': 2}

And here is the code the processes it:

import ast

file = open("testfile.txt", "r")
data = file.readlines()
file.close()

for line in data:
    var_name, var_val = line.split(" = ")
    for possible_num_types in range(3):  # Range is the == number of types we will try casting to
        try:
            var_val = int(var_val)
            break
        except (TypeError, ValueError):
            try:
                var_val = ast.literal_eval(var_val)
                break
            except (TypeError, ValueError, SyntaxError):
                var_val = str(var_val).replace("\n","")
                break
    locals()[var_name] = var_val


print("string_test =", string_test, " :  Type =", type(string_test))
print("integer_test =", integer_test, " :  Type =", type(integer_test))
print("your_dict =", your_dict, " :  Type =", type(your_dict))

This is what that outputs:

string_test = Hello World  :  Type = <class 'str'>
integer_test = 42  :  Type = <class 'int'>
your_dict = {'two': 2, 'one': 1}  :  Type = <class 'dict'>

I really don't like how the casting here works, the try-except block is bulky and ugly. Even worse, you cannot accept just any type! You have to know what you are expecting to take in. This wouldn't be nearly as bad if you only cared about dictionaries, but I really wanted something a bit more universal.

If anybody knows how to better cast these input vars I would LOVE to hear about it!

Regardless, this should still get you there :D I hope I've helped out!


You can use pickle

import pickle
dict = {'one': 1, 'two': 2}
file = open('dump.txt', 'wb')
pickle.dump(dict, file)
file.close()

and to read it again

file = open('dump.txt', 'rb')
dict = pickle.load(file)

EDIT: Guess I misread your question, sorry ... but pickle might help all the same. :)


You could do:

import inspect

mydict = {'one': 1, 'two': 2}

source = inspect.getsourcelines(inspect.getmodule(inspect.stack()[0][0]))[0]
print [x for x in source if x.startswith("mydict = ")]

Also: make sure not to shadow the dict builtin!


Is something like this what you're looking for?

def write_vars_to_file(f, **vars):
    for name, val in vars.items():
        f.write("%s = %s\n" % (name, repr(val)))

Usage:

>>> import sys
>>> write_vars_to_file(sys.stdout, dict={'one': 1, 'two': 2})
dict = {'two': 2, 'one': 1}

1) Make the dictionary:

X = {'a': 1}

2) Write to a new file:

file = open('X_Data.py', 'w')
file.write(str(X))
file.close()

Lastly, in the file that you want the variable to be, read that file and make a new variable with the data from the data file:

import ast
file = open('X_Data.py', 'r')
f = file.read()
file.close()
X = ast.literal_eval(f)