title: Python Error not reading config.cfg?
body: <pre><code>Traceback (most recent call last):
    File "/Users/jondevereux/Desktop/Data reporting/kpex_code/1PD/api_python_publisher_1PD.py", line 40, in &lt;module&gt;
      username = parser.get('api_samples', 'username')
    File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ConfigParser.py", line 607, in get
      raise NoSectionError(section)
  ConfigParser.NoSectionError: No section: 'api_samples'
  </code></pre>
  
  <p>The config file is in the correct directory (same as .py and has the appropriate section api_samples:</p>
  
  <pre><code>[api_samples]
  authentication_url = https://crowdcontrol.lotame.com/auth/v1/tickets
  api_url = https://api.lotame.com/2/
  username = xxx
  password = xxx
  </code></pre>
  
  <p>Script works on co-workers PC not on mine?  I had to use pip to install requests - i'm wondering I i'm missing something else?</p>
  
  <p>Code is as follows:</p>
  
  <pre><code># Set up the libs we need
  import requests
  import sys
  import csv
  import json
  from ConfigParser import SafeConfigParser   # used to get information from a config file
  
  reload(sys)
  sys.setdefaultencoding('utf-8')
  '''
  Now let's get what we need from our config file, including the username and password
  
  We are assuming we have a config file called config.config in the same directory
  where this python script is run, where the config file looks like:
  
  [api_samples]
  authentication_url = https://crowdcontrol.lotame.com/auth/v1/tickets
  api_url = https://api.lotame.com/2/
  username = USERNAME_FOR_API_CALLS
  password = PASSWORD
  
  '''
  # Set up our Parser and get the values - usernames and password should never be in code!
  parser = SafeConfigParser()
  parser.read('config.cfg')
  username = parser.get('api_samples', 'username')
  password = parser.get('api_samples', 'password')
  authentication_url = parser.get('api_samples', 'authentication_url')
  base_api_url = parser.get('api_samples', 'api_url')
  
  # OK, all set with our parameters, let's get ready to make our call to get a Ticket Granting Ticket
  # Add the username and password to the payload (requests encodes for us, no need to urlencode)
  payload = {'username': username,
             'password': password}
  
  # We want to set some headers since we are going to post some url encoded params.
  headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain", "User-Agent":"python" }
  
  # Now, let's make our Ticket Granting Ticket request.  We get the location from the response header
  tg_ticket_location = requests.post(authentication_url, data=payload).headers['location']
  
  # Let's take a look at what a Ticket Granting Ticket looks like:
  # print ('Ticket Granting Ticket - %s \n') % (tg_ticket_location[tg_ticket_location.rfind('/') + 1:])
  
  # Now we have our Ticket Granting Ticket, we can get a service ticket for the service we want to call
  # The first service call will be to get information on behavior id 5990.
  # service_call = base_api_url + 'behaviors/5990'
  
  # Add the service call to the payload and get the ticket
  #payload = {'service': service_call}
  #service_ticket = requests.post( tg_ticket_location, data=payload ).text
  
  # Let's take a look at the service ticket
  #print ('Here is our Service Ticket - %s \n') % ( service_ticket )
  
  '''
  Now let's make our call to the service ... remember we need to be quick about it because
  we only have 10 seconds to do it before the Service Ticket expires.
  
  A couple of things to note:
  
  JSON is the default response, and it is what we want, so we don't need to specify
  like {'Accept':'application/json'}, but we will anyway because it is a good practice.
  
  We don't need to pass any parameters to this call, so we just add the parameter
  notation and then 'ticket=[The Service Ticet]'
  '''
  
  headers = {'Accept':'application/json'}
  
  #behavior_info = requests.get( ('%s?ticket=%s') % (service_call, service_ticket), headers=headers)
  
  # Let's print out our JSON to see what it looks like
  # requests support JSON on it's own, so not other package needed for this
  # print ('Behavior Information: \n %s \n') % (behavior_info.json() )
  
  '''
  Now let's get the names and IDs of some audiences
  
  We can reuse our Ticket Granting Ticket for a 3 hour period ( we haven't passed that yet),
  so let's use it to get a service ticket for the audiences service call.
  
  Note that here we do have a parameter that is part of the call.  That needs to be included
  in the Service Ticket request.
  
  We plan to make a call to the audience service to get the first 10 audiences in the system
  ascending by audience id.  We don't need to pass the sort order, because it defaults to ascending
  '''
  
  # Set up our call and get our new Service Ticket, we plan to sort by id
  
  
  # Please insert audiences ID below:
  
  audienceids = ['243733','243736','241134','242480','240678','242473','242483','241119','243732','242492','243784','242497','242485','243785','242486','242487','245166','245167','245168','245169','245170','245171','240860']
  f = open("publisher_report_1PD.csv", 'w+')
  title_str = ['1PD % Contribution','audienceId','publisherName','audienceName']
  
  print &gt;&gt; f,(title_str)
  for audience_id in audienceids:
      service_call = base_api_url + 'reports/audiences/' + audience_id + '/publisher?stat_interval=LAST_MONTH&amp;page_count=100&amp;page_num=1&amp;sort_attr=audienceName&amp;inc_network=false&amp;sort_order=ASC'
      payload = {'service': service_call}
  
  # Let's get the new Service Ticket, we can print it again to see it is a new ticket
      service_ticket = requests.post( tg_ticket_location, data=payload ).text
  #print ('Here is our new Service Ticket - %s \n') % ( service_ticket )
  
  # Use the new ticket to query the service, remember we did have a parameter this time,
  # so we need to &amp; 'ticket=[The Service Ticket]' to the parameter list
      audience_list = requests.get( ('%s&amp;ticket=%s') % (service_call, service_ticket)).json()
  #print audience_list
  # create an array to hold the audiences, pull ou the details we want, and print it out
  
      audiences = []
  
      for ln in audience_list['stats']:
  
          audiences.append({ 'audienceId': ln['audienceId'], 'audienceName': ln['audienceName'], 'publisherName': ln['publisherName'], '1PD % Contribution': ln['percentOfAudience']})
  
          for ii in range( 0, len(audiences) ):
              data = audiences[ii]
              data_str = json.dumps(data)
              result = data_str.replace("\"","")
              result1 = result.replace("{1PD % Contribution:","")
              result2 = result1.replace("publisherName: ","")
              result3 = result2.replace("audienceName: ","")
              result4 = result3.replace("audienceId: ","")
              result5 = result4.replace("}","")
  
  
          print &gt;&gt; f,(result5)
  
  # Once we are done with the Ticket Granting Ticket we should clean it up'
  remove_tgt = requests.delete( tg_ticket_location )
  print ( 'Status for closing TGT - %s') % (remove_tgt.status_code)
  i = input('YAY! Gotcha!!')
  </code></pre>