Basic Python Training at Grofers - Day 3

Dec 19-21, 2019 Vikrant Patil, Anand Chitipothu

These notes are available online at http://notes.pipal.in/2019/grofers_basic_dec/day3.html

© Pipal Academy LLP

Day 1 | Day 2 | Day 3 | Day 3-part2

We will be using python 3 (>= 3.0) from anaconda for this training. You can download it from

https://www.anaconda.com/download/

Wroking with web API

In [1]:
!pip install requests
Requirement already satisfied: requests in /home/vikrant/anaconda3/lib/python3.7/site-packages (2.22.0)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (3.0.4)
Requirement already satisfied: certifi>=2017.4.17 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (2019.6.16)
Requirement already satisfied: idna<2.9,>=2.5 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (2.8)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (1.24.2)
In [2]:
import requests
In [3]:
resp = requests.get("https://grofers.com/")
In [6]:
print(resp.text[:500])
<!DOCTYPE html>
<html class="no-js" lang="">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
    <link data-react-helmet="true" crossorigin="true" rel="preconnect" href="//webcdn.grofers.com/"/><link data-react-helmet="true" crossorigin="true" rel="preconnect" href="//cdn.grofers.com/"/><link data-react-helmet="true" crossorigin="true" rel="preconnect" href="https://dev.visualwebsiteoptimizer.com"/><li
In [7]:
resp.status_code
Out[7]:
200
In [8]:
!python3 -m pip install requests
Requirement already satisfied: requests in /home/vikrant/anaconda3/lib/python3.7/site-packages (2.22.0)
Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (1.24.2)
Requirement already satisfied: certifi>=2017.4.17 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (2019.6.16)
Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (3.0.4)
Requirement already satisfied: idna<2.9,>=2.5 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from requests) (2.8)
In [10]:
resp = requests.get("http://httpbin.org/get", params={"param1":"python",
                                                     "param2":"xyz"})
In [11]:
print(resp.text)
{
  "args": {
    "param1": "python", 
    "param2": "xyz"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0"
  }, 
  "origin": "157.45.118.131, 157.45.118.131", 
  "url": "https://httpbin.org/get?param1=python&param2=xyz"
}

In [13]:
resp = requests.post("http://httpbin.org/post", 
                     data={"name":"python",
                            "email":"xyz@xyz.com"})
In [14]:
print(resp.text)
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "email": "xyz@xyz.com", 
    "name": "python"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "31", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0"
  }, 
  "json": null, 
  "origin": "157.45.118.131, 157.45.118.131", 
  "url": "https://httpbin.org/post"
}

In [15]:
resp.json()
Out[15]:
{'args': {},
 'data': '',
 'files': {},
 'form': {'email': 'xyz@xyz.com', 'name': 'python'},
 'headers': {'Accept': '*/*',
  'Accept-Encoding': 'gzip, deflate',
  'Content-Length': '31',
  'Content-Type': 'application/x-www-form-urlencoded',
  'Host': 'httpbin.org',
  'User-Agent': 'python-requests/2.22.0'},
 'json': None,
 'origin': '157.45.118.131, 157.45.118.131',
 'url': 'https://httpbin.org/post'}

Example

Find repositories of grofers on git hub

In [19]:
url = "https://api.github.com/orgs/grofers/repos"
repos = requests.get(url).json()
In [20]:
type(repos)
Out[20]:
list
In [21]:
repos[0]
Out[21]:
{'id': 24200966,
 'node_id': 'MDEwOlJlcG9zaXRvcnkyNDIwMDk2Ng==',
 'name': 'freelancer-theme',
 'full_name': 'grofers/freelancer-theme',
 'private': False,
 'owner': {'login': 'grofers',
  'id': 8791674,
  'node_id': 'MDEyOk9yZ2FuaXphdGlvbjg3OTE2NzQ=',
  'avatar_url': 'https://avatars0.githubusercontent.com/u/8791674?v=4',
  'gravatar_id': '',
  'url': 'https://api.github.com/users/grofers',
  'html_url': 'https://github.com/grofers',
  'followers_url': 'https://api.github.com/users/grofers/followers',
  'following_url': 'https://api.github.com/users/grofers/following{/other_user}',
  'gists_url': 'https://api.github.com/users/grofers/gists{/gist_id}',
  'starred_url': 'https://api.github.com/users/grofers/starred{/owner}{/repo}',
  'subscriptions_url': 'https://api.github.com/users/grofers/subscriptions',
  'organizations_url': 'https://api.github.com/users/grofers/orgs',
  'repos_url': 'https://api.github.com/users/grofers/repos',
  'events_url': 'https://api.github.com/users/grofers/events{/privacy}',
  'received_events_url': 'https://api.github.com/users/grofers/received_events',
  'type': 'Organization',
  'site_admin': False},
 'html_url': 'https://github.com/grofers/freelancer-theme',
 'description': 'Jekyll theme based on Freelancer bootstrap theme',
 'fork': True,
 'url': 'https://api.github.com/repos/grofers/freelancer-theme',
 'forks_url': 'https://api.github.com/repos/grofers/freelancer-theme/forks',
 'keys_url': 'https://api.github.com/repos/grofers/freelancer-theme/keys{/key_id}',
 'collaborators_url': 'https://api.github.com/repos/grofers/freelancer-theme/collaborators{/collaborator}',
 'teams_url': 'https://api.github.com/repos/grofers/freelancer-theme/teams',
 'hooks_url': 'https://api.github.com/repos/grofers/freelancer-theme/hooks',
 'issue_events_url': 'https://api.github.com/repos/grofers/freelancer-theme/issues/events{/number}',
 'events_url': 'https://api.github.com/repos/grofers/freelancer-theme/events',
 'assignees_url': 'https://api.github.com/repos/grofers/freelancer-theme/assignees{/user}',
 'branches_url': 'https://api.github.com/repos/grofers/freelancer-theme/branches{/branch}',
 'tags_url': 'https://api.github.com/repos/grofers/freelancer-theme/tags',
 'blobs_url': 'https://api.github.com/repos/grofers/freelancer-theme/git/blobs{/sha}',
 'git_tags_url': 'https://api.github.com/repos/grofers/freelancer-theme/git/tags{/sha}',
 'git_refs_url': 'https://api.github.com/repos/grofers/freelancer-theme/git/refs{/sha}',
 'trees_url': 'https://api.github.com/repos/grofers/freelancer-theme/git/trees{/sha}',
 'statuses_url': 'https://api.github.com/repos/grofers/freelancer-theme/statuses/{sha}',
 'languages_url': 'https://api.github.com/repos/grofers/freelancer-theme/languages',
 'stargazers_url': 'https://api.github.com/repos/grofers/freelancer-theme/stargazers',
 'contributors_url': 'https://api.github.com/repos/grofers/freelancer-theme/contributors',
 'subscribers_url': 'https://api.github.com/repos/grofers/freelancer-theme/subscribers',
 'subscription_url': 'https://api.github.com/repos/grofers/freelancer-theme/subscription',
 'commits_url': 'https://api.github.com/repos/grofers/freelancer-theme/commits{/sha}',
 'git_commits_url': 'https://api.github.com/repos/grofers/freelancer-theme/git/commits{/sha}',
 'comments_url': 'https://api.github.com/repos/grofers/freelancer-theme/comments{/number}',
 'issue_comment_url': 'https://api.github.com/repos/grofers/freelancer-theme/issues/comments{/number}',
 'contents_url': 'https://api.github.com/repos/grofers/freelancer-theme/contents/{+path}',
 'compare_url': 'https://api.github.com/repos/grofers/freelancer-theme/compare/{base}...{head}',
 'merges_url': 'https://api.github.com/repos/grofers/freelancer-theme/merges',
 'archive_url': 'https://api.github.com/repos/grofers/freelancer-theme/{archive_format}{/ref}',
 'downloads_url': 'https://api.github.com/repos/grofers/freelancer-theme/downloads',
 'issues_url': 'https://api.github.com/repos/grofers/freelancer-theme/issues{/number}',
 'pulls_url': 'https://api.github.com/repos/grofers/freelancer-theme/pulls{/number}',
 'milestones_url': 'https://api.github.com/repos/grofers/freelancer-theme/milestones{/number}',
 'notifications_url': 'https://api.github.com/repos/grofers/freelancer-theme/notifications{?since,all,participating}',
 'labels_url': 'https://api.github.com/repos/grofers/freelancer-theme/labels{/name}',
 'releases_url': 'https://api.github.com/repos/grofers/freelancer-theme/releases{/id}',
 'deployments_url': 'https://api.github.com/repos/grofers/freelancer-theme/deployments',
 'created_at': '2014-09-18T18:58:52Z',
 'updated_at': '2018-10-28T06:48:51Z',
 'pushed_at': '2014-09-01T10:11:45Z',
 'git_url': 'git://github.com/grofers/freelancer-theme.git',
 'ssh_url': 'git@github.com:grofers/freelancer-theme.git',
 'clone_url': 'https://github.com/grofers/freelancer-theme.git',
 'svn_url': 'https://github.com/grofers/freelancer-theme',
 'homepage': '',
 'size': 4823,
 'stargazers_count': 0,
 'watchers_count': 0,
 'language': None,
 'has_issues': False,
 'has_projects': True,
 'has_downloads': True,
 'has_wiki': True,
 'has_pages': False,
 'forks_count': 0,
 'mirror_url': None,
 'archived': False,
 'disabled': False,
 'open_issues_count': 0,
 'license': None,
 'forks': 0,
 'open_issues': 0,
 'watchers': 0,
 'default_branch': 'master',
 'permissions': {'admin': False, 'push': False, 'pull': True}}
In [22]:
def get_repo_size(r):
    return r['size']
for repo in sorted(repos, key=get_repo_size)[:5]:
    print(repo['full_name'], repo['size'], repo['forks'])
grofers/mdc-logging 7 0
grofers/ansible-fqdn 12 0
grofers/angulartics-localytics 14 0
grofers/ansible-debian-pgbouncer 22 0
grofers/ansible-rundeck 42 0
In [23]:
for repo in sorted(repos, key=get_repo_size, reverse=True)[:5]:
    print(repo['full_name'], repo['size'], repo['forks'])
grofers/ansible-modules-extras 12931 0
grofers/authomatic 7184 0
grofers/PGObserver 4964 0
grofers/freelancer-theme 4823 0
grofers/paperplane 4291 1

looking through basic html

In [24]:
resp = requests.get("https://grofers.com/")
In [25]:
from bs4 import BeautifulSoup
In [27]:
!python3 -m pip install beautifulsoup4
Requirement already satisfied: beautifulsoup4 in /home/vikrant/anaconda3/lib/python3.7/site-packages (4.7.1)
Requirement already satisfied: soupsieve>=1.2 in /home/vikrant/anaconda3/lib/python3.7/site-packages (from beautifulsoup4) (1.8)
In [28]:
resp = requests.get("https://grofers.com/s/?q=daliya&suggestion_type=0&t=0")
In [29]:
soup = BeautifulSoup(resp.content)
In [31]:
for d in soup.find_all("div", attrs={"class":"plp-product"}):
    name = d.find_all("div", attrs={"class":"plp-product__name"})[0]
    print(name.text)
Grofers Mother's Choice Wheat Daliya/Lapsi
Rajdhani Daliya
Kellogg's Original & the Best Corn Flakes (Carton)
Grofers Happy Day Classic Crunchy Corn Flakes
Kellogg's Original & the Best Corn Flakes (Pouch)
HaveMore Corn Flakes (Pouch)
Kellogg's Almond Corn Flakes
Patanjali Mix Corn Flakes
Bagrry's Original & Healthier Corn Flakes (Pouch)
In [36]:
soup.find_all("div", attrs={"class":"plp-product"})[0].find_all("div", attrs={"class":"plp-product__name"})[0]
Out[36]:
<div class="plp-product__name" data-test-id="plp-product-name" title="Grofers Mother's Choice Wheat Daliya/Lapsi"><div class="plp-product__name--box">Grofers Mother's Choice Wheat Daliya/Lapsi</div></div>
In [39]:
for d in soup.find_all("div", attrs={"class":"plp-product"}):
    name = d.find_all("div", attrs={"class":"plp-product__name"})[0]
    price = d.find_all("div", attrs={"class":"plp-product__price"})[0]
    print(name.text, price.text)
    
Grofers Mother's Choice Wheat Daliya/Lapsi ₹22₹35
Rajdhani Daliya ₹38₹41
Kellogg's Original & the Best Corn Flakes (Carton) ₹179₹180
Grofers Happy Day Classic Crunchy Corn Flakes ₹95₹175
Kellogg's Original & the Best Corn Flakes (Pouch) ₹283₹310
HaveMore Corn Flakes (Pouch) ₹75₹150
Kellogg's Almond Corn Flakes ₹453₹520
Patanjali Mix Corn Flakes ₹150
Bagrry's Original & Healthier Corn Flakes (Pouch) ₹231₹310
In [40]:
import time
In [45]:
time.sleep(0.5)
In [42]:
help(time.sleep)
Help on built-in function sleep in module time:

sleep(...)
    sleep(seconds)
    
    Delay execution for a given number of seconds.  The argument may be
    a floating point number for subsecond precision.

In [46]:
def find_product(name):
    url = "https://grofers.com/s/?q={product}&suggestion_type=0&t=1".format(product=name)
    resp = requests.get(url)
    soup = BeautifulSoup(resp.content)
    products = []
    for d in soup.find_all("div", attrs={"class":"plp-product"}):
        name = d.find_all("div", attrs={"class":"plp-product__name"})[0]
        price = d.find_all("div", attrs={"class":"plp-product__price"})[0]
        products.append((name.text, price.text))
    return products
In [47]:
find_product("daliya")
Out[47]:
[("Grofers Mother's Choice Wheat Daliya/Lapsi", '₹22₹35'),
 ('Rajdhani Daliya', '₹38₹41'),
 ("Kellogg's Original & the Best Corn Flakes (Carton)", '₹179₹180'),
 ('Grofers Happy Day Classic Crunchy Corn Flakes', '₹95₹175'),
 ("Kellogg's Original & the Best Corn Flakes (Pouch)", '₹283₹310'),
 ('HaveMore Corn Flakes (Pouch)', '₹75₹150'),
 ("Kellogg's Almond Corn Flakes", '₹453₹520'),
 ('Patanjali Mix Corn Flakes', '₹150'),
 ("Bagrry's Original & Healthier Corn Flakes (Pouch)", '₹231₹310')]
In [48]:
find_product("onion")
Out[48]:
[('Onion', '₹109₹142'),
 ('Sambar Onion', '₹125₹163'),
 ("Lay's Crispz Herb & Onion Chips", '₹20'),
 ("Lay's Potato Calm Cream & Onion Flavour Chips - Pack of 2", '₹67₹70'),
 ("Lay's Potato Calm Cream & Onion Flavour Chips - Pack of 3", '₹59₹60'),
 ('Cornitos Cheesy Sour Cream & Onion Nachos - Buy 2 Get 1 Free', '₹70₹105'),
 ('Kissan Tomato No Onion No Garlic Sauce (Bottle)', '₹155₹160'),
 ('Too Yumm Veggie Stix Dahi Papdi Chaat Crisps + Chilli Chataka Crisps + Sour Cream & Onion Crisps Combo - Brand Offer',
  '₹49₹51'),
 ("Lay's Potato Calm Cream & Onion Flavour Chips + Potato Joyful Magic Masala Chips Combo",
  '₹63₹70')]
In [49]:
resp = requests.post("http://httpbin.org/post", files={"filename":open("poem.txt")})
In [51]:
print(resp.text)
{
  "args": {}, 
  "data": "", 
  "files": {
    "filename": "The Zen of Python, by Tim Peters\n\nBeautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.\nComplex is better than complicated.\nFlat is better than nested.\nSparse is better than dense.\nReadability counts.\nSpecial cases aren't special enough to break the rules.\nAlthough practicality beats purity.\nErrors should never pass silently.\nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to guess.\nThere should be one-- and preferably only one --obvious way to do it.\nAlthough that way may not be obvious at first unless you're Dutch.\nNow is better than never.\nAlthough never is often better than *right* now.\nIf the implementation is hard to explain, it's a bad idea.\nIf the implementation is easy to explain, it may be a good idea.\nNamespaces are one honking great idea -- let's do more of those!\n"
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "1005", 
    "Content-Type": "multipart/form-data; boundary=12f511970306477cf34d30c18bd3e331", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0"
  }, 
  "json": null, 
  "origin": "157.45.118.131, 157.45.118.131", 
  "url": "https://httpbin.org/post"
}

In [53]:
resp.json()
Out[53]:
{'args': {},
 'data': '',
 'files': {'filename': "The Zen of Python, by Tim Peters\n\nBeautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.\nComplex is better than complicated.\nFlat is better than nested.\nSparse is better than dense.\nReadability counts.\nSpecial cases aren't special enough to break the rules.\nAlthough practicality beats purity.\nErrors should never pass silently.\nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to guess.\nThere should be one-- and preferably only one --obvious way to do it.\nAlthough that way may not be obvious at first unless you're Dutch.\nNow is better than never.\nAlthough never is often better than *right* now.\nIf the implementation is hard to explain, it's a bad idea.\nIf the implementation is easy to explain, it may be a good idea.\nNamespaces are one honking great idea -- let's do more of those!\n"},
 'form': {},
 'headers': {'Accept': '*/*',
  'Accept-Encoding': 'gzip, deflate',
  'Content-Length': '1005',
  'Content-Type': 'multipart/form-data; boundary=12f511970306477cf34d30c18bd3e331',
  'Host': 'httpbin.org',
  'User-Agent': 'python-requests/2.22.0'},
 'json': None,
 'origin': '157.45.118.131, 157.45.118.131',
 'url': 'https://httpbin.org/post'}

classes

In [54]:
%%file bank0.py

balance = 0

def get_balance():
    return balance

def deposit(amount):
    global balance
    balance += amount
    
def withdraw(amount):
    global balance
    balance -= amount
    
Writing bank0.py
In [55]:
import bank0
In [56]:
bank0.get_balance()
Out[56]:
0
In [57]:
bank0.deposit(100)
In [61]:
%%file bank1.py

def make_account():
    return {"balance":0}

def get_balance(account):
    return account['balance']

def deposit(account , amount):
    account['balance'] += amount
    
def withdraw(account, amount):
    account['balance'] -= amount
    
def test_account():
    a1 = make_account()
    assert get_balance(a1) == 0
    deposit(a1, 100)
    assert get_balance(a1) == 100
    withdraw(a1, 50)
    assert get_balance(a1) == 50
    a2 = make_account()
    assert get_balance(a1) == 50
    assert get_balance(a2) == 0
Overwriting bank1.py
In [62]:
!pytest bank1.py
============================= test session starts ==============================
platform linux -- Python 3.7.3, pytest-5.0.1, py-1.8.0, pluggy-0.12.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/vikrant/trainings/2019/grofers_basic_dec
plugins: doctestplus-0.3.0, benchmark-3.2.2, cov-2.8.1, arraydiff-0.3, remotedata-0.3.1, openfiles-0.3.2
collected 1 item                                                               

bank1.py .                                                               [100%]

=========================== 1 passed in 0.02 seconds ===========================
In [60]:
a1 = bank1.make_account()
In [65]:
class BankAccount:
    
    def __init__(self, name, balance):# this constructor
        self.name = name
        self.balance = balance
        
    def get_balance(self):
        return self.balance
    
    
    def deposit(self, amount):
        self.balance += amount
        
    def withdraw(self, amount):
        self.balance -= amount
        
        
        
In [66]:
a1 = BankAccount("Vikrant", 1000)
In [67]:
a1.get_balance()
Out[67]:
1000
In [68]:
a1.deposit(1000)
In [69]:
a1.withdraw(1000)
In [70]:
a1.get_balance()
Out[70]:
1000

-problems

  • Write a class Point which has x and y co-ordiante stored in it. and has interface to add another point.
    p1 = Point(2, 4)
    p2 = Point(3, 4)
    p3 = p1.add(p2)
    print(p3.x, p3.y)
    5 8
In [71]:
class Point:
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def add(self, point):
        x = self.x + point.x
        y = self.y + point.y 
        return Point(x ,y)
In [72]:
p1 = Point(1, 2)
In [73]:
p2 = Point(4, 5)
In [75]:
p3 = p1.add(p2)
In [76]:
p3.x, p3.y
Out[76]:
(5, 7)
In [77]:
p1
Out[77]:
<__main__.Point at 0x7f2e605e2e80>
In [78]:
Point
Out[78]:
__main__.Point
In [79]:
l = [1,2,3]
In [80]:
l
Out[80]:
[1, 2, 3]
In [81]:
p1
Out[81]:
<__main__.Point at 0x7f2e605e2e80>
In [86]:
class Point:
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def add(self, point):
        x = self.x + point.x
        y = self.y + point.y 
        return Point(x ,y)
    
    def __repr__(self):
        return "Point({},{})".format(self.x, self.y)
    
    def __str__(self):
        return "({},{})".format(self.x, self.y)
In [87]:
p = Point(2,3)
In [88]:
p
Out[88]:
Point(2,3)
In [89]:
print(p)
(2,3)
In [92]:
p
Out[92]:
Point(2,3)
In [91]:
repr(p)
Out[91]:
'Point(2,3)'
In [93]:
import time
In [94]:
time.time()
Out[94]:
1576910189.961372

problem

  • Write a class Timer which has method to start timer and stop timer. and a method to get elapsed time. Use this class to time this function.
import time
def wait():
    time.sleep(5)

t =Timer()
t.start()
wait()
t.stop()
print(t.get_elapsed_time())
5.0212

Inheritance

In [95]:
class RedPoint(Point):
    
    color = "red"
In [97]:
r = RedPoint(3, 5)
In [98]:
r
Out[98]:
Point(3,5)
In [99]:
r.add(RedPoint(2,2))
Out[99]:
Point(5,7)
In [100]:
r
Out[100]:
Point(3,5)
In [101]:
print(r)
(3,5)
In [102]:
r.color
Out[102]:
'red'
In [103]:
import unittest
In [104]:
class Test(unittest.TestCase):
    
    def setUp(self):
        print("Setup")
        
    def tearDown(self):
        print("cleaning up")
        
    def test_case1(self):
        print("case1")
        
        
    def test_case2(self):
        print("case2")
In [105]:
 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-105-cb2a0674de24> in <module>
----> 1 unittest.unittest()

AttributeError: module 'unittest' has no attribute 'unittest'

Exceptions

In [107]:
s
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-107-ded5ba42480f> in <module>
----> 1 s

NameError: name 's' is not defined
In [108]:
int("er")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-108-c4a1a283cdd4> in <module>
----> 1 int("er")

ValueError: invalid literal for int() with base 10: 'er'
In [109]:
def read_csv(filename):
    with open(filename) as f: 
        return [[int(c) for c in line.strip().split(",")] for line in f]
    
In [110]:
%%file data.csv
1,2,3
2,3,4
1,2,3
Writing data.csv
In [111]:
read_csv("data.csv")
Out[111]:
[[1, 2, 3], [2, 3, 4], [1, 2, 3]]
In [112]:
%%file data1.csv
1,,3
2,3,4
1,2,3
Writing data1.csv
In [113]:
read_csv("data1.csv")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-113-841660e96f7a> in <module>
----> 1 read_csv("data1.csv")

<ipython-input-109-a57dbecd7cb0> in read_csv(filename)
      1 def read_csv(filename):
      2     with open(filename) as f:
----> 3         return [[int(c) for c in line.strip().split(",")] for line in f]
      4 

<ipython-input-109-a57dbecd7cb0> in <listcomp>(.0)
      1 def read_csv(filename):
      2     with open(filename) as f:
----> 3         return [[int(c) for c in line.strip().split(",")] for line in f]
      4 

<ipython-input-109-a57dbecd7cb0> in <listcomp>(.0)
      1 def read_csv(filename):
      2     with open(filename) as f:
----> 3         return [[int(c) for c in line.strip().split(",")] for line in f]
      4 

ValueError: invalid literal for int() with base 10: ''
In [114]:
def parseint(strnum):
    try:
        return int(strnum)
    except ValueError:
        print("got missing/invalid value!")
        return 0
In [115]:
def read_csv(filename):
    with open(filename) as f: 
        return [[parseint(c) for c in line.strip().split(",")] for line in f]
    
In [116]:
read_csv("data1.csv")
got missing/invalid value!
Out[116]:
[[1, 0, 3], [2, 3, 4], [1, 2, 3]]
In [ ]: