Hello Python


So a few weeks ago, I got interested in python. I have been hearing about python for last one year or so, but it never amazed me much. I would always dismiss it thinking I’m a C guy and python is the abolishment of coding. So I always overlooked the pros. And a while ago, though not so much long, I looked at python-docs. It was Compre(finals) time and I was getting bored. I decided to give a chance to python. I started reading the docs and did couple of codes. It was easy for me to learn python as I already know C and Java. I was amazed to see how easy python is!

A week passed. My interest in python was reducing as I could not shift the gears to upper level. I could do basic coding but not good coding(I still don’t know if my codes are well written or not). I thought to start python again from the basics. This time I searched python on google. And I found this amazing video tutorial by Nick Parlante on google (I downloaded it from DC). I finished it in a day. I knew that I had learned something but was just unable to apply.

I randomly visited many python websites for tutorials and different projects but it was of no use. All the websites listed projects like Django, Twisted, etc. And as a beginner, I don’t think anyone can do these. So I was back where I started.

After a day or two, I stumbled upon to InterviewStreet and there were so many basic codes that were not that easy to do but still a beginner could do them. So I picked up the easiest one and started coding. At first, it really looked redundant. I always took help from those videos. And finally using regular expressions(re), I managed to make it look tidy. This was my first attempt at that code. I uploaded it on InterviewStreet but the code was dismissed as it took more than 16 seconds(a lot probably, I guess). I started to think for different ways in which the time complexity could be reduced. It was a short code, probably 100 lines or so and hence there was not much that I could do to reduce the complexity. I looked up few questions on stackoverflow and even asked one. I got fair amount of replies. So I changed my code and again uploaded it but alas! It still rejected it on time basis. I changed it a bit couple more times and uploaded it. But still the time complexity was high. I didn’t do anything on that code again.

Winter holidays started and I left for Mumbai. It was fun to watch Family Guy – Star Wars movie with Abhinav Gupta in the train but I slept and missed the ending!
Whenever you talk to some person who is good at coding and stuff, the reply you would get – ” I started making apps, writing codes for my daily usage and needs. For example ‘ An alarm’. By making these small things, you would progress.” So I got to thinking and started making something that would be helpful to me. I didn’t find anything that was easy and sensible. I thought to make something insensible and really easy. I started making an app to add contact numbers. So this was my first try at it.
Contacts

#!/usr/bin/python2.7
import sys
import re
import string

def search_contact(dic):
  count=0
  str1 = raw_input('Enter the name:\t')
  temp_str1=str1.lower()
  name=sorted(dic.keys())
  for i in range(len(dic)):
    result = None
    search_name = name[i].lower()
    result = re.search('.*'+temp_str1+'.*',search_name)
    if result:
      try:
        print name[i] + '  ' + dic[name[i]]
        count+=1
      except KeyError:
        print '\n' + str1 + ' not found\n'
  if count==0:
    print '\n' + str1 + ' not found\n'

def add_contact(dic):
  name = raw_input('\nName: ')
  value = raw_input('Number: ')

  if value.isdigit():
    dic[name] = value
    print '\n' + name + ' added to contacts.\n'
  else:
    print 'Please enter only numbers.' + name + ' not added in contacts.'

  return dic

def main():
  dic={}
  n=0
  while n!= 3:
    print '1. Add contact\n2. Search contact\n3. Quit'
    while True:
      try:
        n=int(raw_input('Enter: '))
        break
      except ValueError:
        print 'Please choose a valid option'
    if n==1:
      dic = add_contact(dic)
    elif n==2:
      search_contact(dic)
    elif n==3:
      print 'Quit.'
      return
    else:
      print 'Please enter a valid option'

if __name__ == '__main__':
  main()

It saved contacts in a text file! Ha!

In a few days, I got myself introduced to the database. I particularly liked gdbm! I started improving my code adding new features, etc. I finally came to this: contacts. And needless to say, how much I loved pickle! pickle module was the life saver.

After this I started making a Work Manager for myself. And no, it did not use a text file to save the data. This was my first code(draft).

#!/usr/bin/python2.7
import pickle
import gdbm
import os
import re
import sys
import time
import datetime

'''
Today Date added
Show List added
Date string added
Change date added
Validity check of date added
Add Task added
'''

def check_valid(date):
  year, mon, day = date
  if mon <= 12 and mon>0:
    if day <= 31 and day>0:
      if mon==4 or mon ==6 or mon==9 or mon==11:
        if day > 30:
          return 0
        else:
          return 1
      elif mon==2:
        if year%4 ==0:
          if day>29:
            return 0
          else:
            return 1
        else:
          if day>28:
            return
          else:
            return 1
      else:
        return 1
    else:
      return 0
  else:
    return 0

def get_date_string(date):
  year, mon, day = date
  string = str(mon)+'/'+str(day)+'/'+str(year)

  return string

def get_today():
  date_today = datetime.date.today().timetuple()[:3]
  return date_today

def change_date(date,num):
  year, mon, day = date
  new_year, new_mon, new_day = date

  if mon==1 or mon ==3 or mon==5 or mon==7 or mon==8 or mon==10 or mon==12 :
    if day+num > 31:
      if mon == 12:
        new_mon == 1
        new_year = year+1
        new_date = date+num - 31
      else:
        new_mon=mon+1
        new_date = date+num - 31
    else:
      new_day = day+num
  elif mon==2 :
    if year%4 == 0:
      if day+num > 29:
        new_mon=mon+1
        new_day = day+num - 29
      else:
        new_day = day+num
    else:
      if day+num > 28:
        new_mon = mon+1
        new_day = day+num - 28
      else:
        new_day = day+num
  else:
    if day+num > 30:
      new_mon = mon+1
      new_day = day+num - 30
    else:
      new_day = day+num

  new_date = (new_year,new_mon,new_day)
  return new_date

def get_task_list(date,tmdb):
  task_list=[]
  task_key = pickle.dumps(date)
  try:
    task_list = pickle.loads(tmdb[task_key])
  except KeyError:
    1       # do nothing
  return task_list

def show_task(date,tmdb):
  date_today = get_today()
  if date == date_today:
    print "Today's tasks."
  elif date[0:2]==date_today[0:2]:
    if date[2]==date_today[2]+1:
      print "Yesterday's tasks."
    elif date[2]==date_today[2]-1:
      print "Tomorrow's tasks."
    else:
      print date,'Task.'
  else:
    print date,'Task.'

  task_list = get_task_list(date,tmdb)
  if task_list:
    for i in range(len(task_list)):
      print str(i+1)+'.', task_list[i]
  else:
    print 'No task for',get_date_string(date)

def view_task(tmdb):
  print "1.Task for today.\n2.Task for tomorrow.\n3.Yesterday's task.\n4.Task for some other day.\n5.Exit."
  while True:
   try:
     n=int(raw_input())
     break
   except ValueError:
     print 'Enter int'

  today_date = datetime.date.today().timetuple()[:3]

  if n==1:
    show_task(today_date,tmdb)
  elif n==2:
    date = change_date(today_date,1)
    show_task(date,tmdb)
  elif n==3:
    date = change_date(today_date,-1)
    show_task(date,tmdb)
  elif n==4:
    print 'Enter date(month day year):'
    d = raw_input().split()
    date = (int(d[2]),int(d[0]),int(d[1]))
    if check_valid(date):
      show_task(date,tmdb)
    else:
      print 'Invalid date'
  elif n==5:
    return
  else:
    view_task(tmdb)
    return

def assign_task(tmdb):
  date_today = get_today()
  print '1. Enter Task for today\n2. Enter Task for tomorrow\n3. Enter Task for some other day.\n4. No task'
  while True:
    try:
      n=int(raw_input())
      break
    except ValueError:
      print 'Enter 1, 2 or 3'

  if n==1:
    date=date_today
    task_key = pickle.dumps(date)
  elif n==2:
    date = change_date(date_today,1)
    task_key = pickle.dumps(date)
  elif n==3:
    print 'Enter date(month day year):'
    d = raw_input().split()
    date = (int(d[2]),int(d[0]),int(d[1]))
    if check_valid(date):
      task_key = pickle.dumps(date)
  elif n==4:
    return

  else:
    print 'Incorrect option'
    assign_task(tmdb)
    return
  if task_key:
    task_list=get_task_list(date,tmdb)
    task='42'
    while task!='0':
      print 'Enter Task(0 to end).'
      task = raw_input()
      if task!='0':
        if task:
          task_list.append(task)

    task_str = pickle.dumps(task_list)
    tmdb[task_key]=task_str

def main():
  date = datetime.date.today().timetuple()[:3]
  tmdb=gdbm.open('task-manager1','c')
  show_task(date,tmdb)
  view_task(tmdb)
  assign_task(tmdb)

if __name__ == '__main__':
  main()

I know it looks so shabby but the 3rd and 4th version were horribly huge as I had included almost everything that I could think of.
And the version 5 and 6 were the improved one and also looked a bit nice. Worked well. I even made a notifying code so that whenever I log in I would get a notification of ‘Today’s work’
Task-Manager

#!/usr/bin/python2.7

'''
Today Date added
Show List added
Date string added
Change date added
Validity check of date added
Add Task added
Get Int input added
Task Status added
Check Task added
Remove Task added
Getting Task according to date added
Show Menu added
Priority added
List sorted according to priority and status
Change Priority added
A function named sync_DB added to sync the database
negative days also included in changing the dates
Number of days(from today) included in getting the date of the task
Notes and Description Added
View notes and Description added
change_date() function modified. Now looks good.
check_valid(date) funciton modified.
'''

import pickle
import gdbm
import time
import datetime
from operator import itemgetter
import os

def check_valid(date):
  year, mon, day = date
  year = str(year)
  mon = str(mon)
  day = str(day)
  date = year+mon+day
  try:
    time.strptime(date,'%Y%m%d')
    return 1
  except ValueError:
    return 0

def change_date(num):
  sec = num*24*3600
  sec = time.time()+sec
  t = time.ctime(sec)
  t_struct = time.strptime(t)
  new_date = t_struct[0:3]
  return new_date

def get_date_string(date):
  year, mon, day = date
  string = str(mon)+'/'+str(day)+'/'+str(year)
  return string

def get_today():
  date_today = datetime.date.today().timetuple()[:3]
  return date_today

def get_task_date():
  date_today = get_today()
  print '1. Task for today\n2. Task for tomorrow\n3. Task for yesterday.\n4. Task for some other day.\n5. Exit'
  n=get_int('Choose an option:\t')

  if n==1:
    date=date_today
  elif n==2:
    date = change_date(1)
  elif n==3:
    date = change_date(-1)
  elif n==4:
    date = get_task_from_date()
  elif n==5:
    return

  else:
    print 'Incorrect option'
    date=get_task_date(tmdb)

  return date

def get_task_from_date():
  date_today = get_today()
  print 'Today is', get_date_string(date_today)
  print '1. Number of days after Today.\n2. Number of days before today.\n3. Specific Date.\n4. Exit.'
  n = get_int('Choose an option:\t')

  if n==1 or n==2:
    num = get_int('Number of days\t')
    if n==1:
      date = change_date(num)
    else:
      date = change_date(-num)
  elif n==3:
    print 'Enter date(month day year):'
    d = raw_input().split()
    date = (int(d[2]),int(d[0]),int(d[1]))
    if not check_valid(date):
      date = get_task_from_date()
  elif n==4:
    return
  else:
    print 'Invalid option'
    date = get_task_from_date()
  return date

def get_task_list(date,tmdb):
  task_list=[]
  task_key = pickle.dumps(date)
  try:
    task_list = pickle.loads(tmdb[task_key])
    task_list = sorted(task_list,key=itemgetter(1,2)) # Sort task_list according to status and priority.
    return task_list
  except KeyError:
    return task_list

def get_int(string=''):
  while True:
    try:
      n=int(raw_input(string))
      break
    except ValueError:
      print 'Enter int'
  return n

def get_task_num(date,tmdb):
  show_task(date,tmdb)
  task_list = get_task_list(date,tmdb)
  if task_list:
    n=get_int('Enter the number of the task(0 to exit)')
    if n<0 or n>len(task_list):
      print 'Invalid option'
      n = get_task_num(date,tmdb)
    return n

def show_task_main(tmdb):
  print 'Show Task'
  date = get_task_date()
  if date:
    show_task(date,tmdb)
  return

def show_task(date,tmdb):
  print
  date_today = get_today()
  if date == date_today:
    print "Today's tasks."
  elif date[0:2]==date_today[0:2]:
    if date[2]==date_today[2]-1:
      print "Yesterday's tasks."
    elif date[2]==date_today[2]+1:
      print "Tomorrow's tasks."
    else:
      print date,'Task.'
  else:
    print date,'Task.'

  task_list = get_task_list(date,tmdb)

  if task_list:
    for i in range(len(task_list)):
      print str(i+1)+'.', task_list[i][0],
      if task_list[i][1] == 0:
        if task_list[i][2] == 0:
          print '\t--Urget',
        elif task_list[i][2] == 1:
          print '\t--Important',
        print '\t---Incomplete'
      else:
        print '\t---Completed'
  else:
    print 'No task for',get_date_string(date),'\n'

def assign_task_main(tmdb):
  print 'Assign Task for'
  date = get_task_date()
  if date:
    assign_task(date,tmdb)
  return

def assign_task(date,tmdb):
  task_list=get_task_list(date,tmdb)
  task='42'
  while task!='0':
    print 'Enter Task(0 to end).'
    task = raw_input()
    if task!='0':
      if task:
        priority = get_priority()
        des = get_description()
        notes = get_notes()
        task_list.append([task,0,priority,des,notes])
  tmdb = sync_DB(date,task_list,tmdb)

def get_description():
  des = raw_input('Add Description of the task.(Enter to exit)')
  return des

def get_notes():
  notes = raw_input('Add notes about the task.(Enter to exit)')
  return notes

def show_des_note_main(tmdb):
  print 'Descriptions and Notes'
  date = get_task_date()
  if date:
    show_des_note(date,tmdb)
  return

def show_des_note(date,tmdb):
  n = get_task_num(date,tmdb)
  if n:
    task_list = get_task_list(date,tmdb)
    print task_list[n-1][0],'\nDescription:'
    if task_list[n-1][3]:
      print task_list[n-1][3]
    else:
      print 'No Description about this task'
    print '\nNotes:'
    if task_list[n-1][4]:
      print task_list[n-1][4],'\n'
    else:
      print 'No notes about this task.\n'
  show_des_note_main(tmdb)
  return

def check_task_main(tmdb):
  print 'Check Tasks'
  date = get_task_date()
  if date:
    check_task(date,tmdb)
  return

def check_task(date,tmdb):
  n = get_task_num(date,tmdb)
  if n:
    status=42
    while status!=0 and status!=1:
      status=get_int('Check(1)--Uncheck(0)--Exit(2)')
      if status==2:
        return
    task_list = get_task_list(date,tmdb)
    task_list[n-1][1]=status                  # Change the satus of the task
    tmdb = sync_DB(date,task_list,tmdb)
  check_task_main(tmdb)
  return

def get_priority():
  priority = get_int('Enter Task Priority\n0-Urgent\t1-Important\t2-Normal\tChoose an option\t')
  if priority==0 or priority==1 or priority==2:
    return priority
  else:
    print 'Incorrect option'
    priority = get_priority()
    return priority

def change_priority_main(tmdb):
  print 'Change Priority'
  date = get_task_date()
  if date:
    change_priority(date,tmdb)
  return

def change_priority(date,tmdb):
  n = get_task_num(date,tmdb)
  if n:
    priority=42
    while priority!=0 and priority!=1 and priority!= 2:
      priority=get_int('Urgent(0)--Important(1)--Normal(2)--Exit(3)\t')
      if priority==3:
        return
    task_list = get_task_list(date,tmdb)
    task_list[n-1][2]=priority      # Change the priority
    tmdb = sync_DB(date,task_list,tmdb)
  change_priority_main(tmdb)
  return

def remove_task_main(tmdb):
  print 'Remove Task'
  date = get_task_date()
  if date:
    remove_task(date,tmdb)
  return

def remove_task(date,tmdb):
  n = get_task_num(date,tmdb)
  if n:
    task_list = get_task_list(date,tmdb)
    task_list.remove(task_list[n-1])
    tmdb = sync_DB(date,task_list,tmdb)
    remove_task(date,tmdb)
  else:
    print 'No task.'
  remove_task_main(tmdb)
  return

def sync_DB(date,task_list,tmdb):
  task_key=pickle.dumps(date)
  task_list_str=pickle.dumps(task_list)
  tmdb[task_key]=task_list_str
  return tmdb

def main():
  n=42
  date = datetime.date.today().timetuple()[:3]
  Path = os.path.abspath('')
  tmdb=gdbm.open(Path+'/Taskmanager','c')
  show_task(date,tmdb)
  date = change_date(1)
  show_task(date,tmdb)
  while n!=7:
    n=show_menu()
    if n==1:
      show_task_main(tmdb)
    elif n==2:
      assign_task_main(tmdb)
    elif n==3:
      check_task_main(tmdb)
    elif n==4:
      change_priority_main(tmdb)
    elif n==5:
      remove_task_main(tmdb)
    elif n==6:
      show_des_note_main(tmdb)
    elif n==7:
      tmdb.close()
      return
    else:
      print 'Invalid option'

def show_menu():
  print '1. Show Task.\n2. Assign new task.\n3. Check task.\n4. Change Task Priority.\n5. Remove task.\n6. Show Description and Notes about the task.\n7. Exit.'
  n=get_int('Choose an option:\t')

  return n

if __name__ == '__main__':
  main()

So, when I finished this one, the first one looked so foolish. In the first version, change_date() function is so incompetant and how I managed to change that into this!

def change_date(num):
  sec = num*24*3600
  sec = time.time()+sec
  t = time.ctime(sec)
  t_struct = time.strptime(t)
  new_date = t_struct[0:3]
  return new_date

So, yeah I finished working on my work-manager and started looking for some other things that I could easily do.

So after making these two apps(yeah, I call them apps!), I started reading the Python Library which indeed should be kept under the pillow. Its really apt and useful. I read about eamil, smtplib, imaplib, poplib and implemented it. So I made an app that would allow you to send email with multiple attachments to multiple addresses. And also receive emails and download all the attachments. It took me 2 days to make this app. It was difficult at the beginning but then I always had the answer to the life, Universe and everything! 42!

I started with making a code which would only send email that too without any attachments. I read many articles on the Internet. In particular, this one was really helpful.

http://yuji.wordpress.com/2011/06/22/python-imaplib-imap-example-with-gmail/

And obviously, the python library had it all. So after 30 something hour spent on internet reading about email, MIME, imaplib, smtplib, mailbox, I came up with this one.

Basic-Gmail-API

#!/usr/bin/python2.7
import smtplib
import imaplib
import getpass
import email
import pickle
import base64
import os
from email.MIMEMultipart import MIMEMultipart
from email.Utils import COMMASPACE
from email.MIMEBase import MIMEBase
from email.parser import Parser
from email.MIMEImage import MIMEImage
from email.MIMEText import MIMEText
from email.MIMEAudio import MIMEAudio
import mimetypes

def get_int(string=''):
  while True:
    try:
      n=int(raw_input(string))
      break
    except ValueError:
      print 'Enter int'
  return n

def send_mail(user,server):
  fromaddr = raw_input('Send mail by the name of: ')
  tolist = raw_input('To: ').split()
  sub = raw_input('Subject: ')

  msg = email.MIMEMultipart.MIMEMultipart()
  msg['From'] = fromaddr
  msg['To'] = email.Utils.COMMASPACE.join(tolist)
  msg['Subject'] = sub
  msg.attach(MIMEText(raw_input('Body: ')))
  msg.attach(MIMEText('\nsent via python', 'plain'))
  n=42
  while n != 0:
    n = get_int('1. Attach\n0. Send\nChoose an option: ')
    if n==1:
      msg = attach_files(msg)
    elif n==0:
      server.sendmail(user,tolist,msg.as_string())
      print 'sent'

  return

def attach_files(msg):

  filename = raw_input('File name: ')
  try:
    f = open(filename,'rb')
  except IOError:
    print 'Attachment not found'
    return msg

  ctype, encoding = mimetypes.guess_type(filename)

  if ctype is None or encoding is not None:
    ctype = 'application/octet-stream'

  maintype, subtype = ctype.split('/', 1)

  if maintype == 'text':
    part = MIMEText(f.read(), _subtype=subtype)
  elif maintype == 'image':
    part = MIMEImage(f.read(), _subtype=subtype)
  elif maintype == 'audio':
    part = MIMEAudio(f.read(), _subtype=subtype)
  else:
    part = MIMEBase(maintype, subtype)
    msg.set_payload(f.read())

  part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(filename))
  msg.attach(part)
  f.close()

  return msg

def get_mail(mail):
  MailboxList=[]
  status, mailbox_list = mail.list()
  for i in range(len(mailbox_list)):
    MailboxList.append(mailbox_list[i].split('"')[-2])
    print MailboxList[i]

  mailbox = raw_input('Enter the name of the mailbox: ')

  if mailbox in MailboxList:
    mail.select(mailbox)
    mail = get_unseen(mail)

#  mail.logout()
  return

def get_unseen(mail):
  result, data = mail.uid('search', None, 'UNSEEN')
  uid_list = data[0].split()
  print len(uid_list), 'Unseen emails.'
  get_email(uid_list,mail)
  return mail

def get_email(uid_list,mail):
  for i in range(len(uid_list)):
    email_uid = uid_list[i]
    res, dat = mail.uid('fetch', email_uid, '(RFC822)')
    raw_email = dat[0][1]
    msg = email.message_from_string(raw_email)
    get_email_info(i+1,email_uid,msg)
  return

def get_email_info(i,email_uid,msg):
  print ''
  print 'New email:\n'
  print i,'UID:', email_uid, 'Sender:', email.utils.parseaddr(msg['From'])[0],email.utils.parseaddr(msg['From'])[1]
  print 'Subjct:',msg['Subject']
  print 'Message: '
  print get_body(msg)
  attach_list = get_attach_list(msg)
  print len(attach_list),'Attachments:',attach_list
  n = get_int('1. Download All Attachments\n0. Exit\nChoose an option: ')
  if n==1:
    get_attach(msg)
  return

def get_body(msg):
  for part in msg.walk():
    content_type = part.get_content_type()
    if content_type == 'text/plain' or content_type =='text/html':
      payload = part.get_payload(decode=True)
      if payload:
        print payload
  return

def get_attach_list(msg):
  attach_list=[]
  for part in msg.walk():
    filename = part.get_filename()
    if filename:
      attach_list.append(filename)
  return attach_list

def get_attach(msg):
  for part in msg.walk():
    filename = part.get_filename()
    if filename:
      fp = open('/home/jay/Downloads/'+filename,'wb')
      fp.write(part.get_payload(decode=True))
      fp.close()
  return

def main():
  user = raw_input('Username: ')
  passw = base64.b64encode(getpass.getpass())

  smtp_host = 'smtp.gmail.com'
  smtp_port = 587
  server = smtplib.SMTP()
  server.connect(smtp_host,smtp_port)
  server.ehlo()
  server.starttls()
  server.login(user,base64.b64decode(passw))

  imap_host = 'imap.gmail.com'
  mail = imaplib.IMAP4_SSL(imap_host)
  mail.login(user,base64.b64decode(passw))
  n=42
  while n != 0:
    n = get_int('1. Send email\n2. Get email\n0. Exit\nChoose an option: ')
    if n==1:
      send_mail(user,server)
    elif n==2:
      get_mail(mail)
    elif n==0:
      server.quit()
      mail.logout()
  return

if __name__ == '__main__':
  main()

Winter vacation ended. I came back to campus. I started searching for the usage of python in engineering and I found some websites and codes which are really good.
Two days ago, I started to read about gtk and pygtk. I am making a GUI for my gmail app.
I have already completed the ‘send’ part. And the rest, I will hopefully start in the morning.


Gmail-GUI-API

It’s been really great working with python. If you don’t know about python, please read it up. You will be amazed.

P.S. I still some times type

#!/usr/bin/pytohn2.7
About these ads

3 thoughts on “Hello Python

  1. Nice post! Thanks for the ping.

    You said django isn’t a good place to start as a beginner, but I think it’s the best place to start due to the highly defined scope (it’s to serve HTML) and incredible documentation. It’s actually a python tutorial in itself.

    PS: If you wrap your code in code here[/sourcode], you will get a wordpress syntax highlighted code block.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s