Python – Export to CSV

Exporting data to a CSV file:

import csv

# Create CSV file
f = open('file_name.csv', 'w')
file_writer = csv.writer(f, quotechar='"', quoting=csv.QUOTE_MINIMAL)

# Write headers to CSV file
volume_header = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col7']
file_writer.writerow(volume_header)

# Simplifying the code assuming you have an array of data
for i in array:
	file_writer.writerow([i.val1, i.val2, i.val3, i.val4, i.val5, i.val6, i.val7])
f.close()

Python smtplib – Send email with attachments

Here’s how you can send attachments from email using smtplib

#!/usr/lib/python
import smtplib
import mimetypes
from email.mime.multipart import MIMEMultipart
from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.text import MIMEText

emailfrom = "FROM-EMAIL@DOMAIN.COM"
emailto = "TO-EMAIL@DOMAIN.COM"
fileToSend = "UPLOAD-FILE.csv"

msg = MIMEMultipart()
msg["From"] = emailfrom
msg["To"] = emailto
msg["Subject"] = "YOUR EMAIL SUBJECT"
msg.preamble = "YOUR EMAIL SUBJECT"

ctype, encoding = mimetypes.guess_type(fileToSend)
if ctype is None or encoding is not None:
    ctype = "application/octet-stream"

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

if maintype == "text":
    print 'text'
    fp = open(fileToSend)
    # Note: we should handle calculating the charset
    attachment = MIMEText(fp.read(), _subtype=subtype)
    fp.close()
elif maintype == "image":
    print 'image'
    fp = open(fileToSend, "rb")
    attachment = MIMEImage(fp.read(), _subtype=subtype)
    fp.close()
elif maintype == "audio":
    print 'audio'
    fp = open(fileToSend, "rb")
    attachment = MIMEAudio(fp.read(), _subtype=subtype)
    fp.close()
else:
    print 'else'
    fp = open(fileToSend, "rb")
    attachment = MIMEBase(maintype, subtype)
    attachment.set_payload(fp.read())
    fp.close()
    encoders.encode_base64(attachment)
attachment.add_header("Content-Disposition", "attachment", filename=fileToSend)
msg.attach(attachment)

server = smtplib.SMTP("EMAIL-SERVER.DOMAIN.COM")
server.set_debuglevel(0)
server.sendmail(emailfrom, emailto, msg.as_string())
server.quit()

Python – Iterate over a list and check if it’s not Empty

I have a list that I wanted to iterate over. When I used a list comprehension, it would fail if the list was None. But it would if the list was empty [].

The old and easy way of doing this was:

if tags:
	for t in tags:
		# Do stuff with t

The pythonic way of merging the if statement within the list comprehension is:

for t in [t for t in (tags or [])]:
	# Do stuff with t

If you had a dictionary, you could use a ternary condition within list comprehension:

([k for k, v in tags] if tags is not None else [])

OR, You can embed the ternary condition in the comprehension as well:

[k for k, v in (tags if tags is not None else [])]

The original stack overflow post.

Python Class used like an Enum

Although Enums are available in Python, I just like the idea or am used to using Classes instead which allows me to have more functionality in future if I need to attach additional methods to the class. Here’s how I have typically created a Class to store AWS Regions and have a method all() that would return all the region values – basically hard-coded.

class AwsRegion():
	'''
	Class to define AWS Regions
	'''
	OHIO = 'us-east-2'
	NORTH_VIRGINIA = 'us-east-1'
	NORTH_CALIFORNIA = 'us-west-1'
	OREGON = 'us-west-2'
	MUMBAI = 'ap-south-1'
	SEOUL = 'ap-northeast-2'
	SINGAPORE = 'ap-southeast-1'
	SYDNEY = 'ap-southeast-2'
	TOKYO = 'ap-northeast-1'
	FRANKFURT = 'eu-central-1'
	IRELAND = 'eu-west-1'
	LONDON = 'eu-west-2'
	SAO_PAULO = 'sa-east-1'

	@classmethod
	def all(cls, ):
		return [
			AwsRegion.OHIO,
			AwsRegion.NORTH_VIRGINIA,
			AwsRegion.NORTH_CALIFORNIA, 
			AwsRegion.OREGON,
			AwsRegion.MUMBAI,
			AwsRegion.SEOUL,
			AwsRegion.SINGAPORE,
			AwsRegion.SYDNEY,
			AwsRegion.TOKYO,
			AwsRegion.FRANKFURT,
			AwsRegion.IRELAND,
			AwsRegion.LONDON,
			AwsRegion.SAO_PAULO
			]

But I wanted to make the method all() more dynamic so every time I add new regions to the class, I don’t have to add the region to the all method return list. I found a better way to implement the all() method.

@classmethod
def all(cls, ):
	return [value for name, value in vars(cls).items()
				if not name.startswith('__')
					and not callable(getattr(cls,name))]

The original stack overflow post.

Updating Nulls in SFDC using salesforce-python-toolkit

I had been looking for a long time to update Null into a SFDC field. I wanted to set the date value to current date or reset it to blank based on a condition. I was able to set a date without issues, but clearing the date wouldn’t work. I tried to use ”, ‘null’ and None while trying to blank out the value but nothing worked. I was sure it was a straightforward solution but just didn’t know what it was. I got in touch with the author of the toolkit and he responded back in no time with the solution. I’m sharing the working solution here:

data = {}
if condition==True:
    data['Termination_Date__c'] = '2017-05-12'
else:
    data['fieldsToNull'] = ['Termination_Date__c']

Python functions with arbitrary arguments

A function can be defined in Python with arbitrary number of arguments by prefixing one of the argument with *. e.g. you may have an addition function that sums at least two numbers but user is more than welcome to pass in more arguments. The function would look something like this:

def addition(a, b, *args):
    sum = a+b
    if args:
        for arg in args:
            sum += arg
    return sum

print addition(1,2)  #Will output 3
print addition(1,2,3,4)  #Will output 10

Similarly, you could pass arbitrary number of key-value pairs to a function. e.g. you may have an email function where you would require to pass the to, from, subject and body. The cc and bcc parameters could be optional. You could define a function like this:

def mail(to, subject, body, **kwargs):
    print to
    print subject
    print body
    if kwargs:
        if 'cc' in kwargs:
            print 'Add cc to email'
        if 'bcc' in kwargs:
            print 'Add bcc to email'

mail('to@domain.com', 'Testing', 'Email body') 
#Will send email to recipient with subject and body
mail('to@domain.com', 'Testing', 'Email body', cc='cc@domain.com', bcc='bcc@domain.com')
#Will send email to recipient with subject, body and also cc and bcc recipients

Python smtplib – Send Plaintext and HTML emails

I had to do quite some research to implement email functionality with CC and BCC. Here’s ready to use code. Pass in a dictionary with to, cc, bcc, subject and body and function would do the rest.

#!/usr/bin/python

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def sendPlaintextMail(dict_params):
      email_subject = dict_params['email_subject']
      email_from = "from_email@domain.com"
      email_to = dict_params['email_to']
      email_cc = email_bcc = None
      if 'email_cc' in dict_params and dict_params['email_cc']:
            email_cc = dict_params['email_cc']
      if 'email_bcc' in dict_params and dict_params['email_bcc']:
            email_bcc = dict_params['email_bcc']
      email_body = dict_params['email_body']

      msg = MIMEMultipart('alternative')
      msg['To'] = email_to
      msg['CC'] = email_cc
      msg['Subject'] = email_subject
      mt_html = MIMEText(email_body, 'plain')
      msg.attach(mt_html)

      server = smtplib.SMTP('YOU_MAIL_SERVER.DOMAIN.COM')
      server.set_debuglevel(1)
      toaddrs = [email_to] + [email_cc] + [email_bcc]
      server.sendmail(email_from, toaddrs, msg.as_string())
      server.quit()

def sendHtmlMail(dict_params):
      email_subject = dict_params['email_subject']
      email_from = "from_email@domain.com"
      email_to = dict_params['email_to']
      email_cc = email_bcc = None
      if 'email_cc' in dict_params and dict_params['email_cc']:
            email_cc = dict_params['email_cc']
      if 'email_bcc' in dict_params and dict_params['email_bcc']:
            email_bcc = dict_params['email_bcc']
      email_body = dict_params['email_body']

      msg = MIMEMultipart('alternative')
      msg['To'] = email_to
      msg['CC'] = email_cc
      msg['Subject'] = email_subject
      mt_html = MIMEText(email_body, 'html')
      msg.attach(mt_html)

      server = smtplib.SMTP('YOU_MAIL_SERVER.DOMAIN.COM')
      server.set_debuglevel(1)
      toaddrs = [email_to] + [email_cc] + [email_bcc]
      server.sendmail(email_from, toaddrs, msg.as_string())
      server.quit()

# Calling the mailer functions
dict_params = {}
dict_params['email_to'] = 'to_email@domain.com'
dict_params['email_cc'] = 'cc_email@domain.com'
dict_params['email_bcc'] = 'bcc_email@domain.com'
dict_params['email_subject'] = 'Test message from python library'
dict_params['email_body'] = '<h1>Hello World</h1>'
sendPlaintextMail(dict_params)
sendHtmlMail(dict_params)

Now, if you need to send email to multiple recipients, the msg[‘To’] in the MIMEMultipart needs to be a comma separated string and the toaddrs needs to be a list. So here’s a slight modification that would be required to the above function in order to send it to multiple recipients (although this would work for a single recipient as well).

      .....
      msg = MIMEMultipart('alternative')
      msg['To'] = ",".email_to
      .....
# Calling the mailer functions
dict_params = {}
dict_params['email_to'] = ['to_email@domain.com', 'another_email@domain.com']
.....