Python – CSV handling

If you are going to process CSV’s in Python, you must really use the csv module. It makes life very easy on you and has extensive possibilities. By default, It creates a dictionary containing the header rows as key (eg: “Header 1”), which makes processing a charm.

import csv

coordinates_file = open("data.csv", "rU")
coordinates_data = csv.DictReader(coordinates_file)

for coord in coordinates_data:
    print (coord["Header 1"])

coordinates_file.close()

In the open statement, the “rU” is for universal read, meaning python will figure out line endings. (\r\n or \n or something other).

Another little trick, is once you have loaded a csv file, you can for example make a indexed array by indexing the input with one of the information in the row (assume here patrols is loaded with all the patrols, either from a DB or a CSV file):

patrols_dict = {} #Init to empty
for patrol in patrols:
     patrols_dict[patrol["PatrolID"]] = patrol

#And now we can access a patrol directly by it's patrol ID
#eg. patrols_dict["1000"] to access patrol 1000.

Python – Neat little file http download routine

File downloading in Python is not hard, but this neat little routine also picks up the name of the file to be downloaded from the server if you don’t specify one. Here’s the magic sauce for python 2.x. For Python 3, not much to change, use urllib instead of urlinb2 and urlparse has been merged into urllib.

### Download Section
import urllib2
import urlparse
import shutil
import os
import sys

def download(url, fileName=None):
    def getFileName(url,openUrl):
        if 'Content-Disposition' in openUrl.info():
            # If the response has Content-Disposition, try to get filename from it
            cd = dict(map(lambda x: x.strip().split('=') if '=' in x else (x.strip(),''), openUrl.info()['Content-Disposition'].split(';')))
            if 'filename' in cd:
                filename = cd['filename'].strip("\"'")
                if filename: return filename
        # if no filename was found above, parse it out of the final URL.
        return os.path.basename(urlparse.parse.urlsplit(openUrl.url)[2])
    r = urllib2.urlopen(urllib2.Request(url))
    try:
        fileName = fileName or getFileName(url,r)
        with open(fileName, 'wb') as f:
           shutil.copyfileobj(r,f)
    finally:
        r.close()

I found this on StackOverflow and have been using it happily.

Javascript google maps basics

Today, I had to embed a google maps with both a fixed KML and one generated from a php script. Here is the webpage source with embedded JavaScript:

<!DOCTYPE html>
<html>
<head>Google Maps Javascript API Test</head>
<style type="text/css">
html, body, #map_canvas {
margin: 0;
padding: 0;
height: 100%;
}
</style>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var map;

function initialize() {
var myOptions = { zoom: 11,
center: new google.maps.LatLng(46.045119,7.47757),
mapTypeId: google.maps.MapTypeId.ROADMAP};
map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);

//Base race overlay from static Website
var ctaLayer = new google.maps.KmlLayer('http:// ... /files/pdg.track.kml');
ctaLayer.setMap(map);

//Patrol Marker
var markerOptions = {
position: new google.maps.LatLng(46.03, 7.47),
map: map,
title:"Derniere position"}

var mark = new google.maps.Marker(markerOptions);

//Infowindow contents
var contentString = '<div id="content">'+
'<div id="patrolNotice">'+
'</div>'+
'<h1 id="PatrolID">0001</h1>'+
'<div id="bodyContent">'+
'<p><b>Nom de patrouille</b>, Coureur 1, Coureur 2, Coureur 3'+
'<br>Parti de Zermatt, Depart 22:00</p>'+
'</div></div>';

var infowindow = new google.maps.InfoWindow({
content: contentString});

//Function for the click on marker infowindow
google.maps.event.addListener(mark, 'click', function() {
infowindow.open(map, mark);});

//Path used by the patrol
var prevPath = [
new google.maps.LatLng(46.03, 7.47),
new google.maps.LatLng(46.00, 7.40),
new google.maps.LatLng(45.99, 7.39),
new google.maps.LatLng(45.97, 7.37)];

var PathPoly = new google.maps.Polyline({
path: prevPath,
strokeColor: "#00FF00",
strokeOpacity: 1.0,
strokeWeight: 3,
map : map});
}
//Initialization of the map on window load
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map_canvas" style="width: 1024px;height: 500px"></div>
</body>
</html>

This creates a basic map, initialises it with a static KML and adds a marker with a clickable information panel at a location set in JS.

KML File structure

I needed to make a KML suitable for reading in Google Earth. Here’s the template:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<NetworkLinkControl> <!-- Set minimum refresh to 3 minutes -->
 <minRefreshPeriod>180</minRefreshPeriod> 
</NetworkLinkControl>
<Document>
<name>pdg2012.kml</name>
<!-- Definition des styles du KML -->
<Style id="My_Style1">
 <IconStyle> <Icon> <href>ball.png</href> </Icon></IconStyle> <!-- Transparent PNG must be in same folder on server -->
</Style> 
<Style id="My_Style2">
 <IconStyle> <Icon> <href>ball2.png</href> </Icon></IconStyle>
</Style> 
<Folder>
<name>Patrouille des glaciers</name>
<Placemark><name>Dossard 1</name>
<description>Echo, Foxtrot, Golf</description>
<Point><coordinates>7.35162,46.22549,0</coordinates></Point>
<styleUrl>#My_Style1</styleUrl> 
</Placemark>
<Placemark><name>Dossard 2</name>
<description>Alpha, Bravo, Charlie</description>
<Point><coordinates>7.35196,46.2254,0</coordinates></Point>
<styleUrl>#My_Style2</styleUrl> <!-- Styles must be defined-->
</Placemark>
</Folder>
</Document>
</kml>

The minRefreshPeriod indicates to Google Earth not to load the KML file too often when a network link is directed to it.

Adding windows printers with a VBScript

I had to add four network printers to a set of thirty laptops, so to make that faster, I used this small VBScript.

On Error Resume Next 
'SETS 'LOAD DRIVER' PRIVILEGE. 
    Set objWMIService = GetObject("Winmgmts:") 
    objWMIService.Security_.Privileges.AddAsString "SeLoadDriverPrivilege", True
'SETS PRINTER PORT. 
    Set objNewPort = objWMIService.Get _
      ("Win32_TCPIPPrinterPort").SpawnInstance_
    objNewPort.Name = "IP_192.168.1.5" 
    objNewPort.Protocol = 1 
    objNewPort.HostAddress = "192.168.1.5" 
    objNewPort.PortNumber = "9100" 
    objNewPort.SNMPEnabled = False 
    objNewPort.Put_
'SETS PRINTER TO PORT. 
    Set objPrinter = objWMIService.Get _ 
        ("Win32_Printer").SpawnInstance_ 
    objPrinter.DriverName = "HP LaserJet 2100" 
    objPrinter.PortName   = "IP_192.168.1.5" 
    objPrinter.DeviceID   = "NB1" 
    'objPrinter.Location = "Front Office" 
    objPrinter.Network = True 
    objPrinter.Shared = False 
    objPrinter.Put_
'SETS PRINTER AS DEFAULT. 
    Set colInstalledPrinters =  objWMIService.ExecQuery _ 
        ("Select * from Win32_Printer Where Name = 'NB1'") 
    For Each objPrinter in colInstalledPrinters 
        objPrinter.SetDefaultPrinter() 
    next

I adapted scripts found on gallery.technet.microsoft.com (for example http://gallery.technet.microsoft.com/scriptcenter/710bb2ad-9a8d-42cb-b142-cda2c1452548).

I added four different IP addresses, one for each printer, port was 9100, standard for hp printing, named the script InstallAll.vbs and then applied it on each computer. A normal double script on the script should launch it.

The one problem I found was that having installed all the printers under the administrator account, the default printer was not set for the user accounts, even if the printers were present.