0

i was trying to loop on txt files which contain dictionary
my code is reading it as string also tried changing those txt file to json but as those words are in single quotes so it say:
Expecting property name enclosed in double quotes
code

for jfile in file_txt.glob('*.txt')            
      with jfile.open('r') as ifile:
          lines_dict=ifile.read()
          for page, word in lines_dict.items():
                    lines = convert_text_to_lines(word)

error

    for page, word in lines_dict.items():
AttributeError: 'str' object has no attribute 'items'

example of my txt file

{1: [((86, 27, 168, 50), 'haha'), ((85, 53, 195, 63), ' work for you.'), ((323, 49, 408, 57),       'Total  due'), ((534, 42, 590, 59), '4.10'), ((323, 66, 515, 77), ' do not need to make')}
robin
  • 49
  • 1
  • 7
  • What the file contains is a string representation of a dict - not an actual dict. It's a bit like looking at the picture of a book - you can't flip its pages but you can use the picture to find the real book. In your case you must first convert the file contents back to an actual dict, e.g. via `ast.literal_eval`. – MisterMiyagi Feb 13 '21 at 05:40
  • Is that the actual content of your file? Are you sure there isn't, say, a closing `]` missing near the end? – MisterMiyagi Feb 13 '21 at 06:02

3 Answers3

1

In your case lines_dict is of type str and not dict,that why you cannot unpack it .So use literal_eval method from ast module.

Signature solution is posted

import glob
import ast
for jfile in glob.glob('*.txt'):
      print(jfile)
      with open(jfile,'r') as ifile:
          lines_dict=ast.literal_eval(ifile.read())
          for page, word in lines_dict.items():
                    lines = convert_text_to_lines(word)
Prajot Kuvalekar
  • 5,128
  • 3
  • 21
  • 32
0

The problem is that read() returns a string, and a string doesn't have any attribute 'items' unlike dictionaries. The other answer which suggested using readlines() is incorrect as well because that would just return a list. (Edit : looks like the answer got deleted, but nevertheless).

Two things:

  1. I assume you copied your text data incorrectly, there was a ] bracket missing at the end.

2) json.load() would have been a great solution to the problem had your data used double quotes instead of single quotes. Turns out even had the data had double quotes, the integer keys and tuples would be a problem like MisterMiyagi pointed out in the comments.


Anyway one work around is to use ast.literal_eval() (which is a bit safer than raw eval)

for jfile in file_txt.glob('*.txt'):        
    with jfile.open('r') as ifile:   
        lines_dict=ast.literal_eval(ifile.read())

For eval vs ast.literal_val, see here

Ayush
  • 1,510
  • 11
  • 27
  • Please avoid suggesting that Python notation is "almost" JSON. People will get the wrong impression and try to convert one to the other. There are far more differences than whether "had your data used double quotes instead of single quotes". Even just in the example shown, JSON would choke on the integer keys and tuples. – MisterMiyagi Feb 13 '21 at 06:00
-1

If the text file would contain a JSON object, then a way to convert it into a Python dictionary would be to use the json module:

import json 

for jfile in file_txt.glob('*.txt')            
      with jfile.open('r') as ifile:
          lines_dict=json.load(ifile)

The problem is that the sample of the txt file is not a JSON object. In the JSON format keys must be strings enclosed in double quotes, but in the example the first key is an integer 1. Strings which are values need to be enclosed in double quotes too, but in the example they are enclosed in single quotes e.g. 'haha'. Furthermore, tuples are not recognized by JSON. Additionally, in the example there is a closing square bracket missing just before the final brace. If this last issue is fixed then the string could be converted into a Python dictionary using the eval function, but this carries the usual risks:

for jfile in file_txt.glob('*.txt')            
      with jfile.open('r') as ifile:
          lines_dict = eval(ifile.read())
bb1
  • 7,174
  • 2
  • 8
  • 23