I am fairly new to python and need help taking a json file and incorporating
it into the init in a class to be used through out, but I am getting the error below and don't understand why. I have a build a few classes before and this seems to look the same.
AttributeError: 'dict' object has no attribute 'zipcode'
I have a separate json file called config.json that I have changed some information in (i.e. location and api key), but other than that, this is what I am working with.
config.json:
{
"unit_system":"metric",
"location_information":{
"country_code":"US",
"country_name":"United States",
"city":"New York City",
"state":"New York",
"postal":10001
},
"api_keys":{
"weather_api_key":"97a484e1039b7a0779b59f2e57e597a3"
}
}
weather.py
class weather:
"""weather retrieving app"""
def __init__(self, data):
"""initialize attributes for weather app"""
self.unit_system = data['unit_system']
#unit system
self.country_code = data['location_information']['country_code']
self.zipcode = data['location_information']['postal']
#location information
self.api_key = data['api_keys']['weather_api_key']
#api key informaation
def get_update(self):
threading.Timer(5.0, w.get_update).start()
#runs get_update every 5 seconds
#get weather information
weather_url = 'http://api.openweathermap.org/data/2.5/weather?zip=' \
+ str(self.zipcode) + ',' \
+ self.country_code + '&appid=' \
+ self.api_key
weather_request = requests.get(weather_url)
weather_data = weather_request.json()
temp_k = float(weather_data['main']['temp'])
#determine unit system conversions
if self.unit_system == 'english':
temp = (temp_k - 273.15) * 1.8 + 32
elif self.unit_system == 'metric':
temp = temp_k - 273.15
print(temp)
#return(temp)
import threading
import requests
import json
with open('config.json') as config_file:
config = json.load(config_file)
w = weather(config)
w.get_update()
Remove the last line and put these lines at the bottom. The first line creates an instance of class weather named weather_obj. You can then call the get_update using weather_obj
weather_obj = weather(config)
weather_obj.get_update()
The scipt you have provided seems to be working.
a screenshot of my output(s)
Related
#!/usr/bin/env python3
import json
import locale
import sys
import emails
import os
import reports
def load_data(filename):
"""Loads the contents of filename as a JSON file."""
with open(filename) as json_file:
data = json.load(json_file)
return data
def format_car(car):
"""Given a car dictionary, returns a nicely formatted name."""
return "{} {} ({})".format(car["car_make"], car["car_model"], car["car_year"])
def process_data(data):
"""Analyzes the data, looking for maximums.
Returns a list of lines that summarize the information.
"""
locale.setlocale(locale.LC_ALL, 'en_US.UTF8')
max_revenue = {"revenue": 0}
max_sales = {"total_sales": 0}
years_count = {}
for item in data:
# Calculate the revenue generated by this model (price * total_sales)
# We need to convert the price from "$1234.56" to 1234.56
item_price = locale.atof(item["price"].strip("$"))
item_revenue = item["total_sales"] * item_price
if item_revenue > max_revenue["revenue"]:
item["revenue"] = item_revenue
max_revenue = item
# also handle max sales
if item["total_sales"] > max_sales["total_sales"]:
max_sales = item
# also handle most popular car_year
if item["car"]["car_year"] in years_count:
years_count[item["car"]["car_year"]] = {"count": years_count[item["car"]["car_year"]]["count"]+1, "total_sales": years_count[item["car"]["car_year"]]["total_sales"]+item["total_sales"]}
else:
years_count[item["car"]["car_year"]] = {"count": 1, "total_sales": item["total_sales"]}
popular_year = sorted(years_count.items(),key=lambda x: x[1]["count"], reverse=True)[0]
summary = ["The {} generated the most revenue: ${}".format(format_car(max_revenue["car"]), max_revenue["revenue"]),
"The {} had the most sales: {}".format(format_car(max_revenue["car"]), max_sales["total_sales"]),
"The most popular year was {} with {} sales.".format(popular_year[0],popular_year[1]["total_sales"])]
return summary
def cars_dict_to_table(car_data):
"""Turns the data in car_data into a list of lists."""
table_data = [["ID", "Car", "Price", "Total Sales"]]
for item in car_data:
table_data.append([item["id"], format_car(item["car"]), item["price"], item["total_sales"]])
return table_data
def main(argv):
"""Process the JSON data and generate a full report out of it."""
data = load_data("../car_sales.json")
summary = process_data(data)
print(summary)
# turn this into a PDF report
table_data = cars_dict_to_table(data)
reports.generate("/tmp/cars.pdf", "Sales summary for last month", "<br/>".join(summary), table_data)
# send the PDF report as an email attachment
sender = "automation#example.com"
receiver = "{}#example.com".format(os.environ.get('USER'))
subject = "Sales summary for last month"
body = "\n".join(summary)
message = emails.generate(sender, receiver, subject, body, "/tmp/cars.pdf")
emails.send(message)
if __name__ == "__main__":
main(sys.argv)
local.error:unsupported local setting means locale file are n't present
first run command :
locale -a on bash shell they will provide present file
C
C.UTF-8
POSIX
edit the above given code :locale.setlocale(locale.LC_ALL, 'en_US.UTF8')
new code: locale.setlocale(locale.LC_ALL,'C.UTF-8')
I'm trying to figure out how to make the objects I create inside a definition appear on the same workspace as my "name == main" area, so I can call it in other definitions. I don't think I can use a simple "return" statement in my def, because my function is designed to create n-number of objects of a particular class.
def book_to_object(subfolders):
# converts my dictionary of book titles and volumes into individual book objects
for key, val in subfolders.items():
title = replace_spaces_with_underscores(key)
# check to see if book already exists in the registry
if title in [book.name for book in Book._registry]:
print("Book already exists")
else:
exec(title + " = Book(subfolders ,key, Fpath)")
The whole program below.
I'm calling this def from my if __name__ == '__main__': function
print("Done")
#converts my dictionary of book titles and volumes into individual book objects
book_to_object(subfolders)
Originally I had the code in my def in the name=main area of my code but I wanted to reduce the clutter and make it into a definition to give me more flexibility later.
The whole program below.
import os
#get date modified time of a file to determine which file is the newest
def get_date_modified(file):
return os.path.getmtime(file)
#replace spaces with underscores in a string
def replace_spaces_with_underscores(string):
aa = string.replace(" ", "_")
bb= aa.replace('-', '_')
cc= bb.replace("__", "_")
title = cc.replace("__", "_")
return title
# create a list of volumes that have not been exported
def get_unexported_volumes(self):
unexported_volumes = []
for volume in self.volumes:
if volume not in self.last_exported:
unexported_volumes.append(volume)
return unexported_volumes
def book_to_object(subfolders):
# converts my dictionary of book titles and volumes into individual book objects
for key, val in subfolders.items():
title = replace_spaces_with_underscores(key)
# check to see if book already exists in the registry
if title in [book.name for book in Book._registry]:
print("Book already exists")
else:
exec(title + " = Book(subfolders ,key, Fpath)")
class Book(object):
#__metaclass__ = IterBook
_registry = []
#constructor
def __init__(self, my_dict, key, Fpath):
self._registry.append(self)
self.name = key
self.volumes = my_dict[key]
self.Filepath = Fpath + "/" +self.name
#self.last_exported = self.volumes[0]
self.last_exported = ""
self.newest = self.volumes[-1]
self.last_downloaded = self.volumes[-1]
self.last_converted = self.volumes[-1]
self.last_exported_date = get_date_modified(self.Filepath + "/" + self.last_exported)
self.newest_date = get_date_modified(self.Filepath + "/" + self.newest)
self.last_downloaded_date = get_date_modified(self.Filepath + "/" + self.last_downloaded)
self.last_converted_date = get_date_modified(self.Filepath + "/" + self.last_converted)
self.last_exported_volume = self.last_exported
self.newest_volume = self.newest
self.last_downloaded_volume = self.last_downloaded
self.last_converted_volume = self.last_converted
self.last_exported_volume_date = self.last_exported_date
self.newest_volume_date = self.newest_date
self.last_downloaded_volume_date = self.last_downloaded_date
self.last_converted_volume_date = self.last_converted_date
self.last_exported_volume_name = self.last_exported
self.newest_volume_name = self.newest
self.unexported_volumes = get_unexported_volumes(self)
if __name__ == '__main__':
print("Starting")
# File Paths for Debugging purposes
Fpath = '~/'
F_Temp_path = '~/temp'
#parses directory for book based on folder names
subfolders = {'Encyclopedia': ['Vol.001', 'Vol.002', 'Vol.003', 'Vol.004', 'Vol.005'], 'Enginnering_Encyclopedia': ['Avionics', 'Civil', 'Electrical', 'Materials', 'Mechanical']}
print("Done")
#converts my dictionary of book titles and volumes into individual book objects
book_to_object(subfolders)
Notes:
In case anyone is wondering why I'm using objects instead of keeping everything in dictionaries, I need the flexibility that objects give.
Variables such as, file_paths and subfolders are dynamic and are based on what directory the user gives and what files are in that directory, for the purpose of asking the questions they have been hard coded so someone could copy and paste my code and reproduce the problem in question.
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
Basically what I am trying to do is generate a json list of SSH keys (public and private) on a server using Python. I am using nested dictionaries and while it does work to an extent, the issue lies with it displaying every other user's keys; I need it to list only the keys that belong to the user for each user.
Below is my code:
def ssh_key_info(key_files):
for f in key_files:
c_time = os.path.getctime(f) # gets the creation time of file (f)
username_list = f.split('/') # splits on the / character
user = username_list[2] # assigns the 2nd field frome the above spilt to the user variable
key_length_cmd = check_output(['ssh-keygen','-l','-f', f]) # Run the ssh-keygen command on the file (f)
attr_dict = {}
attr_dict['Date Created'] = str(datetime.datetime.fromtimestamp(c_time)) # converts file create time to string
attr_dict['Key_Length]'] = key_length_cmd[0:5] # assigns the first 5 characters of the key_length_cmd variable
ssh_user_key_dict[f] = attr_dict
user_dict['SSH_Keys'] = ssh_user_key_dict
main_dict[user] = user_dict
A list containing the absolute path of the keys (/home/user/.ssh/id_rsa for example) is passed to the function. Below is an example of what I receive:
{
"user1": {
"SSH_Keys": {
"/home/user1/.ssh/id_rsa": {
"Date Created": "2017-03-09 01:03:20.995862",
"Key_Length]": "2048 "
},
"/home/user2/.ssh/id_rsa": {
"Date Created": "2017-03-09 01:03:21.457867",
"Key_Length]": "2048 "
},
"/home/user2/.ssh/id_rsa.pub": {
"Date Created": "2017-03-09 01:03:21.423867",
"Key_Length]": "2048 "
},
"/home/user1/.ssh/id_rsa.pub": {
"Date Created": "2017-03-09 01:03:20.956862",
"Key_Length]": "2048 "
}
}
},
As can be seen, user2's key files are included in user1's output. I may be going about this completely wrong, so any pointers are welcomed.
Thanks for the replies, I read up on nested dictionaries and found that the best answer on this post, helped me solve the issue: What is the best way to implement nested dictionaries?
Instead of all the dictionaries, I simplfied the code and just have one dictionary now. This is the working code:
class Vividict(dict):
def __missing__(self, key): # Sets and return a new instance
value = self[key] = type(self)() # retain local pointer to value
return value # faster to return than dict lookup
main_dict = Vividict()
def ssh_key_info(key_files):
for f in key_files:
c_time = os.path.getctime(f)
username_list = f.split('/')
user = username_list[2]
key_bit_cmd = check_output(['ssh-keygen','-l','-f', f])
date_created = str(datetime.datetime.fromtimestamp(c_time))
key_type = key_bit_cmd[-5:-2]
key_bits = key_bit_cmd[0:5]
main_dict[user]['SSH Keys'][f]['Date Created'] = date_created
main_dict[user]['SSH Keys'][f]['Key Type'] = key_type
main_dict[user]['SSH Keys'][f]['Bits'] = key_bits
The purpose of this form is to let users enter a lot of places (comma separated) and it'll retrieve the phone, name, website. Have it working in a python IDE, no problem, but having issues putting it into my webapp.
I'm getting the error Exception Value: Can't pickle local object 'GetNums.<locals>.get_data' at the line where a is assigned. I checked the type of inputText and verified that it is indeed a list. So, I'm not sure why it won't pickle.
def GetNums(request):
form = GetNumsForm(request.POST or None)
if form.is_valid():
inputText = form.cleaned_data.get('getnums')
# all experimental
inputText = inputText.split(',')
def get_data(i):
#DON'T FORGET TO MOVE THE PRIMARY KEY LATER TO SETTINGS
r1 = requests.get('https://maps.googleapis.com/maps/api/place/textsearch/json?query=' + i + '&key=GET_YOUR_OWN')
a = r1.json()
pid = a['results'][0]['place_id']
r2 = requests.get('https://maps.googleapis.com/maps/api/place/details/json?placeid=' + pid + '&key=GET_YOUR_OWN')
b = r2.json()
phone = b['result']['formatted_phone_number']
name = b['result']['name']
try:
website = b['result']['website']
except:
website ='No website found'
return ' '.join((phone, name, website))
v = str(type(inputText))
with Pool(5) as p:
a = (p.map(get_data, inputText))
# for line in p.map(get_data, inputText):
# print(line)
#code assist by http://stackoverflow.com/a/34512870/5037442
#end experimental
return render(request, 'about.html', {'v': a})
It's actually barfing when trying to pickle get_data, which is a nested function/closure.
Move get_data out of GetNums (and agh rename it to snake_case please) and it should work.