Hi I'm pretty new to python. I try to make a chatbot with rasa for personal use. Would like to add weather api now. I use weatherstack.com. If I use their example this works, but if I adjust it to my own liking I always end up with the same error.
condition = api_response['current']['weather_descriptions'] TypeError: list indices must be integers or slices, not str
This is the code I am using.
class Actionweatherapi(Action):
def name(self):
return "actions.weatherapi"
def run(self, dispatcher, tracker, domain):
import requests
location = tracker.get_slot('location')
if location == 'None':
location = 'fetch:ip'
api_result = requests.get('http://api.weatherstack.com/current?access_key=0000000&query={}'.format(location))
api_response = api_result.json()
country = api_response['request']['query']
condition = api_response['current']['weather_descriptions']
temperature_c = api_response['current']['temperature']
humidity = api_response['current']['humidity']
wind_mph = api_response['current']['wind_speed']
response = """It is currently {} in {} at the moment. The temperature is {} degrees, the humidity is {}% and the wind speed is {} mph.""".format(condition, country, temperature_c, humidity, wind_mph)
dispatcher.utter_message(response)
return [AllSlotsReset()]
I have also reviewed the printf-style String Formatting on the python website, but I cannot figure out how to get it working.
The json response is like this example
http://api.weatherstack.com/current?access_key=1c80e8b9fe4fcef4f8d6fd7514a8e9e9&query=New%20York
Related
I am using flask and web3.eth on pythonanywhere and connecting to a contract, but am having issues returning a value for one of the smart contract functions. No errors are being logged. I have placed several print statements to see where the app is stopping and found that it stops when I call a smart contract function.
Also I should mention that I am able to run this exact code locally without issues.
This is the function that is most likely failing:
def getDataFromTokenID(tokenid, contract):
print('getting uri')
uri = contract.functions.tokenURI(tokenid).call() # This is where it stops printing
print('PRINT:',uri)
html = requests.get(uri)
name, img_url = html.json()['name'], html.json()['image']
code = name[-5:]
return name, img_url, code
The function above is called in the following blueprint:
#TokenInfo.route('/rarity/<int:tokenid>', methods=['GET'])
def sendTokenInfo(tokenid):
contract_address = ' ' # left empty for posting purposes
w3 = Web3(Web3.WebsocketProvider(' ')) # left empty purposefully as well
contract = w3.eth.contract(address=contract_address, abi=contract_abi.abi)
model = Shape_classifier()
model.load_state_dict(load(os.getcwd()+'/mysite/app/state_dict.pth'))
uri = current_app.config['MONGO_URI']
mongo.init_app(current_app, uri)
gs = mongo.db.gantomstone_info
try:
id_exists = [{"$match": {'_id': tokenid}}, {"$count": "count"}]
list(gs.aggregate(id_exists))[0]
except:
print('getting data from token id')
name, img_url, serial = getDataFromTokenID(tokenid, contract) ## Stops printing here
print('opening image')
img = Image.open(requests.get(img_url, stream=True).raw)
shape = getImageShape(img, model)
colors = getColors(getCounts(img))
rgb_count = getCounts(img)
serialTF = getCodeInfo(serial)
to_db = {'_id': tokenid, 'name': name, 'img_url': img_url, 'serial': serial,
'shape': shape, 'colors': colors, 'serialTF': serialTF, 'rgb_count': rgb_count}
gs.insert_one(to_db)
rarity = getRarity(gs, tokenid)
gs.update_one({'_id': tokenid}, {
'$set': {'rarity_values': rarity}}, upsert=True)
to_json = list(gs.find({'_id': tokenid}))[0]
return jsonify(to_json)
I have tried moving contract address around (both out of TokenInfo view function and into the functions file) to no avail. I have also tried changing the function inputs to receive the get request args instead of the int in the URL, which made no difference either.
If the code uses websockets it won't currently work in web apps on PythonAnywhere.
Greeting
I am working on RASA chatbot. I am handling Custom actions for a particular intent using below code. In the custom action I want to get current intent value. SO i dont know that line of code which can give me value of current intent
#this file will be used to all custom actions
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import requests
import json
from zeep import Client
from random import randint
from rasa_core.actions.action import Action
from rasa_core.events import SlotSet
class ActionWeather(Action):
RANDOMIZE = False
#staticmethod
def required_fields():
return [
EntityFormField("period", "period"),
EntityFormField("product", "product")
]
def name(self):
return 'action_weather'
def run(self,dispatcher, tracker, domain):
#Get Slot values
loc = tracker.get_slot('period')
pro = tracker.get_slot('product')
custname= tracker.get_slot('custName')
#Here I want to get Intent Values as well same like slot value in above code
# So what is code for getting intent value
#make json
data = {}
data['period'] = loc
data['product'] = pro
json_data = json.dumps(data)
jsonobj= json.loads(json_data)
#code for SOAP
client = Client('my webservice URL/testsoap?wsdl')
result = client.service.getData(json_data)
print('**********************')
print(result)
print('#######################')
jsonobj= json.loads(result)
#print(response.content)
#json_response = response.json()
#print (json_response)
result1=jsonobj[0]['result']
#result1=randint(1, 100)
#result='X'
response = """sale is {} """.format(result1)
dispatcher.utter_message(response)
#return [SlotSet('location',loc)]
return []
I want to get current and last value of intent in RASA Core in same way as we can get slots value product = tracker.get_slot('product') in python custom action code. Please help.
This works for me:
def run(self,dispatcher, tracker, domain):
intent = tracker.latest_message['intent'].get('name')
rasa-core 0.11.12
rasa-core-sdk 0.11.5
rasa-nlu 0.13.7
intent = json.dumps(tracker.latest_message.intent)
print(intent)
#particular intent name
print(json.loads(intent)['intent']['name'])
outcome
(u'{"confidence": 0.9092543377510975, "name": "greet"}')
or try this
intent = json.dumps(tracker.latest_message.__dict__)
You can use something like below,
currentIntent = tracker.latest_message.intent["name"]
Is a dictionary the correct way to be doing this? Ideally this will be more then 5+ deep. Sorry my only language experience is powershell there I would just make an array of object. Im not looking for someone to write the code I just wanna know if there is a better way?
Thanks
Cody
My Powershell way:
[$title1,$title2,$title3]
$titleX.comment = "comment here"
$titleX.comment.author = "bob"
$titleX.comment.author.karma = "200"
$titleX.comment.reply = "Hey Bob love your comment."
$titleX.comment.reply.author = "Alex"
$titleX.comment.reply.reply = "I disagree"
#
Python code Borken:
import praw
d = {}
reddit = praw.Reddit(client_id='XXXX',
client_secret='XXXX',
user_agent='android:com.example.myredditapp:'
'v1.2.3 (by /u/XXX)')
for submission in reddit.subreddit('redditdev').hot(limit=2):
d[submission.id] = {}
d[submission.id]['comment'] = {}
d[submission.id]['title']= {}
d[submission.id]['comment']['author']={}
d[submission.id]['title'] = submission.title
mySubmission = reddit.submission(id=submission.id)
mySubmission.comments.replace_more(limit=0)
for comment in mySubmission.comments.list():
d[submission.id]['comment'] = comment.body
d[submission.id]['comment']['author'] = comment.author.name
print(submission.title)
print(comment.body)
print(comment.author.name)
print(d)
File "C:/git/tensorflow/Reddit/pull.py", line 23, in <module>
d[submission.id]['comment']['author'] = comment.author.name
TypeError: 'str' object does not support item assignment
#
{'6xg24v': {'comment': 'Locking this version. Please comment on the [original post](https://www.reddit.com/r/changelog/comments/6xfyfg/an_update_on_the_state_of_the_redditreddit_and/)!', 'title': 'An update on the state of the reddit/reddit and reddit/reddit-mobile repositories'}}
I think your approach using a dictionary is okay, but you might also solve this by using a data structure for your posts: Instead of writing
d[submission.id] = {}
d[submission.id]['comment'] = {}
d[submission.id]['title']= {}
d[submission.id]['comment']['author']={}
d[submission.id]['title'] = submission.title
you could create a class Submission like this:
class Submission(object):
def __init__(self, id, author, title, content):
self.id = id
self.author = author
self.title = title
self.content = content
self.subSubmissions = {}
def addSubSubmission(self,submission):
self.subSubmission[submission,id] = submission
def getSubSubmission(self,id):
return self.subSubmission[id]
by using you could change your code to this
submissions = {}
for sm in reddit.subreddit('redditdev').hot(limit=2):
submissions[sm.id] = Submission(sm.id, sm.author, sm.title, sm.content)
# I am not quite sure what these lines are supposed to do, so you might be able to improve these, too
mySubmission = reddit.submission(id=sm.id)
mySubmission.comments.replace_more(limit=0)
for cmt in mySubmission.comments.list():
submissions[sm.id].addSubSubmission(Submission(cmt.id, cmt.title, cmt.author, cmt.body))
By using this apporach you are also able to export the code to readout the comments/subSubmissions into an extra function which can call itself recursively, so that you can read infitive depths of the comments.
Im working on a small project of retrieving information about books from the Google Books API using Python 3. For this i make a call to the API, read out the variables and store those in a list. For a search like "linkedin" this works perfectly. However when i enter "Google", it reads the second title from the JSON input. How can this happen?
Please find my code below (Google_Results is the class I use to initialize the variables):
import requests
def Book_Search(search_term):
parms = {"q": search_term, "maxResults": 3}
r = requests.get(url="https://www.googleapis.com/books/v1/volumes", params=parms)
print(r.url)
results = r.json()
i = 0
for result in results["items"]:
try:
isbn13 = str(result["volumeInfo"]["industryIdentifiers"][0]["identifier"])
isbn10 = str(result["volumeInfo"]["industryIdentifiers"][1]["identifier"])
title = str(result["volumeInfo"]["title"])
author = str(result["volumeInfo"]["authors"])[2:-2]
publisher = str(result["volumeInfo"]["publisher"])
published_date = str(result["volumeInfo"]["publishedDate"])
description = str(result["volumeInfo"]["description"])
pages = str(result["volumeInfo"]["pageCount"])
genre = str(result["volumeInfo"]["categories"])[2:-2]
language = str(result["volumeInfo"]["language"])
image_link = str(result["volumeInfo"]["imageLinks"]["thumbnail"])
dict = Google_Results(isbn13, isbn10, title, author, publisher, published_date, description, pages, genre,
language, image_link)
gr.append(dict)
print(gr[i].title)
i += 1
except:
pass
return
gr = []
Book_Search("Linkedin")
I am a beginner to Python, so any help would be appreciated!
It does so because there is no publisher entry in volumeInfo of the first entry, thus it raises a KeyError and your except captures it. If you're going to work with fuzzy data you have to account for the fact that it will not always have the expected structure. For simple cases you can rely on dict.get() and its default argument to return a 'valid' default entry if an entry is missing.
Also, there are a few conceptual problems with your function - it relies on a global gr which is bad design, it shadows the built-in dict type and it captures all exceptions guaranteeing that you cannot exit your code even with a SIGINT... I'd suggest you to convert it to something a bit more sane:
def book_search(search_term, max_results=3):
results = [] # a list to store the results
parms = {"q": search_term, "maxResults": max_results}
r = requests.get(url="https://www.googleapis.com/books/v1/volumes", params=parms)
try: # just in case the server doesn't return valid JSON
for result in r.json().get("items", []):
if "volumeInfo" not in result: # invalid entry - missing volumeInfo
continue
result_dict = {} # a dictionary to store our discovered fields
result = result["volumeInfo"] # all the data we're interested is in volumeInfo
isbns = result.get("industryIdentifiers", None) # capture ISBNs
if isinstance(isbns, list) and isbns:
for i, t in enumerate(("isbn10", "isbn13")):
if len(isbns) > i and isinstance(isbns[i], dict):
result_dict[t] = isbns[i].get("identifier", None)
result_dict["title"] = result.get("title", None)
authors = result.get("authors", None) # capture authors
if isinstance(authors, list) and len(authors) > 2: # you're slicing from 2
result_dict["author"] = str(authors[2:-2])
result_dict["publisher"] = result.get("publisher", None)
result_dict["published_date"] = result.get("publishedDate", None)
result_dict["description"] = result.get("description", None)
result_dict["pages"] = result.get("pageCount", None)
genres = result.get("authors", None) # capture genres
if isinstance(genres, list) and len(genres) > 2: # since you're slicing from 2
result_dict["genre"] = str(genres[2:-2])
result_dict["language"] = result.get("language", None)
result_dict["image_link"] = result.get("imageLinks", {}).get("thumbnail", None)
# make sure Google_Results accepts keyword arguments like title, author...
# and make them optional as they might not be in the returned result
gr = Google_Results(**result_dict)
results.append(gr) # add it to the results list
except ValueError:
return None # invalid response returned, you may raise an error instead
return results # return the results
Then you can easily retrieve as much info as possible for a term:
gr = book_search("Google")
And it will be far more tolerant of data omissions, provided that your Google_Results type makes most of the entries optional.
Following #Coldspeed's recommendation it became clear that missing information in the JSON file caused the exception to run. Since I only had a "pass" statement there it skipped the entire result. Therefore I will have to adapt the "Try and Except" statements so errors do get handled properly.
Thanks for the help guys!
I have a homework assignment that I have been stuck on for several days.
Basic problem description:
Incident class has properties: ID, time, type, location, narrative and status
methods: init, brief, isMorning, resolve
script takes one argument, the full path of crime report csv.
First few lines of CSV:
ID Time Type Location Narrative
1271 11:54 AM Drug Violation Wolf Ridge Report of possible drug violation. Student was referred to the university.
My code so far:
import sys
class Incident:
def __init__(self, ID, time, type, location, narrative, status):
self.ID = id
self.time = time
self.type = type
self.location = location
self.narrative = narrative
self.status = status
def brief(self):
print '''{0}: {1}, {2}
{3}
'''.format(self.ID, self.type, self.status, self.narrative)
def isMorning(self):
if 'AM' in self.time:
return True
else:
return False
def resolve(self):
if self.status == 'Pending':
self.status = 'Resolved'
try:
dataset = sys.argv[1] except IndexError:
print 'Usage: Requires full path input file name.'
sys.exit()
# Create an empty list to contain the Incident objects. crimeList = []
# Read the crime report. with open(dataset, 'r') as f:
# Read the header.
headers = f.readline().split(',')
# Read each record and parse the attributes.
for line in f:
lineList = line.strip().split(',')
reportNumber = lineList[0]
timeReported = lineList[1]
incidentType = lineList[2]
location = lineList[3]
narrative = lineList[4]
status = lineList[5].strip()
### Create initialize an Incident object instance and store it in a variable
crime = Incident(reportNumber, timeReported, incidentType, location, narrative, status)
### Append the new Incident object to the crimeList.
crimeList.append(crime)
What i'm stuck on:
I need to access the "nth" Incident in the crimeList and run various methods. I can't seem to find a way to access the item and have it functional to run methods on.
I've tried enumerating and splicing but just can't get anything to work?
Anyone have any suggestions?
Look up the nth crime from your crimeList like so: x=crimeList[n], and then call the methods on that instance: x.brief(), x.resolve(), etc.