I am trying to analyze the sentiment of each given sentence from a text file line by line. The code is working whenever I am using the hard coded sentences from the first question linked. When I use the text file input, I get the TypeError.

This is related to the question asked here. And the line by line from text file code is coming from this question:

The first one works, the second with the text-file ("I love you. I hate him. You are nice. He is dumb") does not work. Here is the code :

from pycorenlp import StanfordCoreNLP
nlp = StanfordCoreNLP('http://localhost:9000')
results = []    
with open("c:/nlp/test.txt","r") as f:
    for line in f.read().split('\n'):
        print("Line:" + line)
        res = nlp.annotate(line,
                   properties={
                       'annotators': 'sentiment',
                       'outputFormat': 'json',
                       'timeout': 1000,
                   })
        results.append(res)      

for res in results:             
    s = res["sentences"]         
    print("%d: '%s': %s %s" % (
        s["index"], 
        " ".join([t["word"] for t in s["tokens"]]),
        s["sentimentValue"], s["sentiment"]))

I get this error:

line 21, in

s["index"],

TypeError: list indices must be integers or slices, not str

2

There are 2 best solutions below

0
On BEST ANSWER

Looks like I solved the problem. As londo pointed out: This line sets S as List, but it should be dict, just like in the original code:

s = res["sentences"] 

I moved the code into the same loop where the file is read and analyzed line by line and I print the result directly there. So the new code looks like this:

from pycorenlp import StanfordCoreNLP

nlp = StanfordCoreNLP('http://localhost:9000')

with open("c:/nlp/test.txt","r") as f:
    for line in f.read().split('\n'):
        res = nlp.annotate(line,
                    properties={
                        'annotators': 'sentiment',
                        'outputFormat': 'json',
                        'timeout': 15000,
                   }) 
        for s in res["sentences"]:
            print("%d: '%s': %s %s" % (
            s["index"], 
            " ".join([t["word"] for t in s["tokens"]]),
            s["sentimentValue"], s["sentiment"]))

The result looks just as intended and without any error message:

0: 'I love you .': 3 Positive
0: 'I hate him .': 1 Negative
0: 'You are nice .': 3 Positive
0: 'He is dumb .': 1 Negative
6
On

I did not install the Stanfort-lib, so I couldn't test with its system. but the way, it is returning let me thing that your results-variable is of type "List of Dicts" or some nested type

anyway I made a test

results = []    

with open("tester.txt","r") as f:
    for line in f.read().split('\n'):
        print("Line:" + line)
        sentences = [
        {
            "index":1,
            "word":line,
            "sentimentValue": "sentVal",
            "sentiment":"senti"
        }
    ]
    results.append(sentences) 

then I build your loop and tweaked it a little to fit my needs, like:

for res in results:         
    for s in res:         
        print("%d: '%s': %s %s" % (
            s["index"], 
            " ".join(s["word"]),
            s["sentimentValue"], s["sentiment"]))

what printed me the following

1: 'I   l o v e   y o u .': sentVal senti
1: 'I   h a t e   h i m .': sentVal senti
1: 'Y o u   a r e   n i c e .': sentVal senti
1: 'H e   i s   d u m b': sentVal senti

So basically the code works. but you have to figure out of what type the returning value is, after it gets back from that Stanfort API -> "type(results)" for example

when you have this info, you can start with a loop that goes through the values and if you don't know of what type the nested value is, you call anotehr print of type. Go all the way down until you reach the layer with the items you want to work with

One last thing to point out. In the description you linked, in the Notes. There he informs about how to pass text into the API. And there he explains that the API gets rid of slicing and formatting, you shall only send the whole text. In case you get no results back to keep that in mind