Reputation: 31
I'm learning python with the book: "Python Crash Course: A Hands-On, Project-Based Introduction to Programming". In chapter 17 of the book "Working with APIs", I did as the book says, but an error is occurring. I don't know what the error means. Does that mean there is something wrong with the site-packages? How to fix it?
import requests
import pygal
from pygal.style import LightColorizedStyle as LCS, LightenStyle as LS
# Make an API call, and store the response.
url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
r = requests.get(url)
print("Status code:", r.status_code)
# Store API response in a variable.
response_dict = r.json()
print("Total repositories:", response_dict['total_count'])
# Explore information about the repositories.
repo_dicts = response_dict['items']
names, plot_dicts = [], []
for repo_dict in repo_dicts:
names.append(repo_dict['name'])
plot_dict = {
'value': repo_dict['stargazers_count'],
'label': repo_dict['description'],
}
plot_dicts.append(plot_dict)
# Make visualization.
my_style = LS('#333366', base_style=LCS)
my_config = pygal.Config()
my_config.x_label_rotation = 45
my_config.show_legend = False
my_config.title_font_size = 24
my_config.label_font_size = 14
my_config.major_label_font_size = 18
my_config.truncate_label = 15
my_config.show_y_guides = False
my_config.width = 1000
chart = pygal.Bar(my_config, style=my_style)
chart.title = 'Most-Starred Python Projects on GitHub'
chart.x_labels = names
chart.add('', plot_dicts)
chart.render_to_file('python_repos.svg')
the error is below
Status code: 200
Total repositories: 2198954
Traceback (most recent call last):
File "2018-07-13-1.py", line 45, in <module>
chart.render_to_file('python_repos.svg')
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\graph\public.py", line 114, in render_to_file
f.write(self.render(is_unicode=True, **kwargs))
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\graph\public.py", line 52, in render
self.setup(**kwargs)
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\graph\base.py", line 217, in setup
self._draw()
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\graph\graph.py", line 933, in _draw
self._plot()
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\graph\bar.py", line 146, in _plot
self.bar(serie)
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\graph\bar.py", line 116, in bar
metadata)
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\util.py", line 233, in decorate
metadata['label'])
File "C:\Users\Administrator\AppData\Roaming\Python\Python35\site-packages\pygal\_compat.py", line 61, in to_unicode
return string.decode('utf-8')
AttributeError: 'NoneType' object has no attribute 'decode'
Upvotes: 3
Views: 1749
Reputation: 1
H=''
names, plot_dicts = [],[]
for repo_dict in repo_dicts:
names.append(repo_dict['name'])
if repo_dict['description']is not None:
H = repo_dict['description']
plot_dict = {
'value': repo_dict['stargazers_count'],
'label':H,
}
plot_dicts.append(plot_dict)
Upvotes: 0
Reputation: 991
The error is caused by one of the labels you're setting on the chart being None
, which is one of Python's special built-in constants. When pygal comes to render the chart it expects the label to be a string and calls the decode
function. This function doesn't exist on a None
object, so the error is raised.
Looking at the name and descriptions of the Github repositories (which you're setting as the x labels and data labels, respectively) we can see that the description for one of the repositories is None
. I wouldn't say there is anything particularly wrong with the code from the book, it's just bad luck that one of the most starred Python repositories at this moment in time has no description.
We can work around this by checking for None
values in the for loop:
for repo_dict in repo_dicts:
if repo_dict['name'] is None:
names.append('') # Empty string.
else:
names.append(repo_dict['name'])
plot_dict = {'value': repo_dict['stargazers_count']}
if repo_dict['description'] is not None:
plot_dict['label'] = repo_dict['description']
plot_dicts.append(plot_dict)
In the first part we've added an empty string in place of any None
values (because you'll need something there when you set the x labels).
In the second part we've created the dict with just the value, then added the description as a label only if the description is not None
.
Upvotes: 1