0

I made a dictionary from one file and need to write it into another file that I will be making edits to. To do this, I made a dictionary from the first file and made it into a string to write it to a second file. Is there a way to convert this string back into a dictionary?

An example of the first file is:

123 2
125 5
128 3

which I make into a dictionary and make into a string in the second file:

def CreateNew(prefix, old_file):
    new_file = open('new_file_name', 'w')
    new_file.write(str(old_file))
    new_file.close()
    return new_file

Now, I need to make edits to some of the values in this new file, but am not sure how to make this dictionary string back into a dictionary. I wanted to just print this off to test it out:

def EmpTrans(transactions_file, new_file):
    print(dict(new_file))

but this gives me an empty dictionary {}.
I'm trying not to use any modules for this. I was able to use eval().

TheStrangeQuark
  • 2,257
  • 5
  • 31
  • 58
  • The wide variety of libraries and modules is one of Python's biggest strengths. You can then do something like `import ast` then `my_dict = ast.literal_eval(my_dictionary_string)` and `my_dict` will be of type `dict`. – TigerhawkT3 Apr 06 '15 at 19:31
  • 1
    possible duplicate of [Converting a String to Dictionary?](http://stackoverflow.com/questions/988228/converting-a-string-to-dictionary) – Celeo Apr 06 '15 at 19:32
  • Adding the requirement of not using any modules pretty much guarantees answers that either introduce possible security issues or don't fill all requirements. The right way to do this, as stated in the answer for the recommended duplicate question, is with `ast.literal_eval()`, which uses the `ast` module. – TigerhawkT3 Apr 06 '15 at 21:38
  • The process of saving Python objects to file is called serialization. Reading https://docs.python.org/2/library/pickle.html may give you a different (better) path to achieve your goal. – boardrider Apr 07 '15 at 19:11

3 Answers3

1

To print a dictionary to a file:

output_file = open(path_to_stored_dictionary, 'w')
output_file.write(str(my_dictionary))
output_file.close()

To read a dictionary from a file:

my_dictionary = open(path_to_stored_dictionary, 'r').read()
my_dictionary = eval(my_dictionary)

Note @TigerhawkT3's comment:

...eval() executes code, which can be dangerous if untrusted sources will be sending strings to this function.

Community
  • 1
  • 1
jksnw
  • 648
  • 1
  • 7
  • 19
  • What if dictionary isn't really a dictionary? There could be arbitrary code in there. – Peter Wood Apr 06 '15 at 19:36
  • @PeterWood Are you saying I should add a line of code at the top creating the variable `my_dictionary`? Or is this method flawed? I'm assuming that `my_dictionary` is a dictionary, I did generalise the answer but I'm sure the OP can get it's easy to write dictionary to a file and that the `eval()` function can turn a string (that was dictionary) back to a dictionary. – jksnw Apr 06 '15 at 19:52
  • 1
    He's saying that `eval()` executes code, which can be dangerous if untrusted sources will be sending strings to this function. – TigerhawkT3 Apr 06 '15 at 19:59
  • 1
    @TigerhawkT3. Thanks, I didn't know that, it's a good point. It sounds like the the function will only be used by the OP but I'll point out your comment in my answer. – jksnw Apr 06 '15 at 20:23
  • 1
    In this case, I would use ast.literal_eval instead. – Ben Apr 06 '15 at 21:54
  • I didn't know that either. But I will be using eval because only I will be using the code. – TheStrangeQuark Apr 06 '15 at 22:24
0

To turn your string back into a dictionary, you would split the string into a tuple of key, value pairs. To do so, you would split it.

def get_dict(s):
    return dict(map(lambda kv: kv.split(" "), s.split("\n")))

But I would advise against this. In this case, you should use the Pickle module, except if you don't absolutely trust the data. See also: How can I use pickle to save a dict?.

import pickle

def dump(dict_, file):
    with open(file + ".pickle", "wb") as handle:
        pickle.dump(dict_, handle)

def load(file):
    with open(file + ".pickle", "rb") as handle:
        return pickle.load(handle)

The dict_ can really be any object.

Community
  • 1
  • 1
0

Another secure function is using JSON. Here i use the json.dump() and json.load() functions. The only handicap, is that json load returns strings as unicode string, therefor i am using an own JSONDecoder class that calls super and then traverses the result to encode the strings:

import json
from types import *

# your own decoder class to convert unicode to string type
class MyJSONDecoder(json.JSONDecoder):

    # decode using our recursive function
    def decode(self,json_string):
        return self._decode_obj(super(MyJSONDecoder,self).decode(json_string))

    # recursive function to traverse lists
    def _decode_list(self,data): 
        decoded = []
        for item in data:
            if type(item) is UnicodeType:   item = item.encode('utf-8')
            elif type(item) is ListType:    item = self._decode_list(item)
            elif type(item) is DictType:    item = self._decode_obj(item)
            decoded.append(item)
        return decoded

    # recursive function to traverse objects
    def _decode_obj(self,data): 
        decoded = {}
        for key, value in data.iteritems():
            if type(key) is UnicodeType:    key = key.encode('utf-8')
            if type(value) is UnicodeType:  value = value.encode('utf-8')
            elif type(value) is ListType:   value = self._decode_list(value)
            elif type(value) is DictType:   value = self._decode_obj(value)
            decoded[key] = value
        return decoded

# the dictionary to save
dict = {
    "123": 2,
    "125": 4,
    "126": 5,
    "128": 6
}

# decoder instance
my_decoder = MyJSONDecoder()

# write object to file
with open('serialized.txt', 'w') as new_file:
    json.dump(dict, new_file)
    new_file.close()
    print "Original", dict

# read object from file
with open ("serialized.txt", "r") as old_file:
    dictcopy = my_decoder.decode(old_file.read())
    old_file.close()
    print "**Copy**", dictcopy
hexerei software
  • 3,100
  • 2
  • 15
  • 19