This is a program to extract/compile car NAV .KWI extensions. Unfortunately, I do not know anything about Python though I will love to learn some time very soon. Could you help me compile this into an executable file for windows 7?

Will be reatly appreciated.

#!/usr/bin/env python
#
#       kiwi
#
#       Copyright 2009 Bert Vermeulen <bert@biot.com>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import os
import sys
from getopt import getopt
import string
from datetime import datetime
import struct

EXTRACT_BUFSIZE = 1024 * 1024


def usage():
	print """usage: kiwi [-v|-x] [-o outputdir] -d <dvd directory>
  -v	list modules contained in the LOADING.KWI FILE
  -x	extract modules from the LOADING.KWI file
  -d	directory where the DVD is mounted
  -o	target dir to extract modules into"""
	sys.exit(1)


def is_printable(text):
	for i in text:
		if i not in string.printable + '\x00':
			return False

	return True


def show_date(stamp):
	date = datetime.fromtimestamp(stamp)
	datestr = "%d-%.2d-%.2d" % (date.year, date.month, date.day)

	return datestr


def maybe_dump(text):
	if is_printable(text):
		return text
	else:
		hex = ''
		for i in text:
			hex += "%.2x " % int(ord(i))
		return hex


def show_kwi_info(lo):
	print "number of systems found:", lo['num_systems']
	syscnt = 1
	for s in lo['systems']:
		print "System %s\n    Manufacturer ID: %s" % (syscnt, maybe_dump(s['mid']))
		print "    Number of modules in this system:", len(s['modules'])
		modcnt = 1
		for modname, modversion, category, startdate, enddate, title, info, address, size in s['modules']:
			print "    Module %d:" % modcnt
			print "\tName:", modname
			print "\tVersion:", modversion
			print "\tCategory:", category
			if startdate:
				print "\tValid from:", show_date(startdate)
			if enddate:
				print "\tValid until:", show_date(enddate)
			print "\tAddress: 0x%X" % address
			size += 0.0
			if size > 1024 * 1024:
				size /= 1024 * 1024
				unit = "MB"
			elif size > 1024:
				size /= 1024
				unit = "KB"
			else:
				unit = "bytes"
			print "\tSize: %.1f %s" % (size, unit)

			print
			modcnt += 1

		syscnt += 1


def extract_modules(path, targetdir, system=1):
	try:
		lo = kiwi.parse_loading(path)
		if lo['num_systems'] < system:
			raise Exception, "only %s systems found" % lo['num_systems']

		if not os.path.exists(targetdir):
			os.mkdir(targetdir)

		s = lo['systems'][system-1]
		print "extracting modules into %s..." % targetdir
		fp = open(path)
		for modname, modversion, category, startdate, enddate, title, info, address, size in s['modules']:
			print "  ", modname
			fp.seek(address)
			cnt = 0
			outfile = open(targetdir + '/' + modname, 'w')
			while True:
				if cnt + EXTRACT_BUFSIZE > size:
					chunksize = size - cnt
				else:
					chunksize = EXTRACT_BUFSIZE
				buf = fp.read(chunksize)
				outfile.write(buf)
				cnt += chunksize
				if len(buf) < EXTRACT_BUFSIZE:
					break
			outfile.close()
		fp.close()
	except Exception, msg:
		print "Error:", str(msg)


module_categories = [
	'Initial program',
	'Program',
	'Library',
	'Data'
]

def parse_loading(path):
	lostruct = {}
	fp = open(path)
	data = fp.read(4)
	num_systems, dummy = struct.unpack_from(">HH", data)
	lostruct['num_systems'] = num_systems
	offset = 4
	lostruct['systems'] = []
	for s in range(num_systems):
		system = {}
		fp.seek(offset)
		data = fp.read(16)
		mid, num_modules, dummy = struct.unpack_from(">12sHH", data)
		offset += 16
		system['mid'] = mid
		system['modules'] = []
		# get Module Identification Information blocks
		for m in range(num_modules):
			fp.seek(offset)
			data = fp.read(64)
			cat, modname, modversion = struct.unpack_from(">cxxx52s4s", data)
			offset += 64
			cat = ord(cat)
			category = module_categories[cat & 3]
			if cat & 64:
				category += " (Test module)"
			if cat & 128:
				category += " (Diagnostic service module)"
			modname = modname.rstrip('\x00')
			system['modules'].append([modname, modversion, category])
		# get Module Management Information blocks
		address_multiplier = 0
		for m in range(num_modules):
			fp.seek(offset)
			data = fp.read(256)
			startdate, enddate, title, info, address, size = struct.unpack_from(">HH64s182sIH", data)
			offset += 256
			# dates are in number of days since 1997-01-01 00:00:00. that's
			# 852073200 seconds since the unix epoch, convert to that
			# if it's 0 no date is set, so preserve that
			if startdate:
				startdate += 852073200 + (startdate * 86400)
			if enddate:
				enddate += 852073200 + (enddate * 86400)
			# address is either in 2048-byte sized blocks, or some odd 3-byte
			# block size. try to grok this by the first one we
			# see, which will be right past this this Loading Module Management
			# block we're parsing now
			if m == 0:
				if address < 0x100:
					# too small to be an absolute address
					address_multiplier = 2048
				elif (address >> 8) < 0x100:
					address_multiplier = 8
				else:
					address_multiplier = 1
			address *= address_multiplier
			# size is in 2048-byte sized blocks
			size *= 2048
			system['modules'][m] += [startdate, enddate, title, info, address, size]
		lostruct['systems'].append(system)

	return lostruct




#
# main
#

opts, args = getopt(sys.argv[1:], "vxd:o:")

mode = dvddir = targetdir = None
for opt, arg in opts:
	if opt == '-v':
		if mode:
			usage()
		else:
			mode = 'view'
	elif opt == '-x':
		if mode:
			usage()
		else:
			mode = 'extract'
	elif opt == '-d':
		dvddir = arg
	elif opt == '-o':
		targetdir = arg

if not mode or not dvddir:
	usage()

try:
	path = dvddir + '/LOADING.KWI'
	if not os.path.exists(path):
		print "no LOADING.KWI found in %s" % dvddir
		sys.exit(1)
except Exception, msg:
	print "failed to open %s: %s" % (path, str(msg))
	sys.exit(1)
else:
	if mode == 'view':
		kwi_info = parse_loading(path)
		show_kwi_info(kwi_info)
	elif mode == 'extract':
		if not targetdir:
			print "please set a target directory to extract into."
			usage()
		else:
			extract_modules(path, targetdir)

Dani AI

Generated

A quick troubleshooting checklist and practical route to a Windows 7 executable.

The kiwi script as posted is a Python‑2 era program and appears to have been copied with HTML entities (for example &gt;, &amp;) that must be fixed to literal > and & before running. It also reads a binary DVD file, so all file opens on Windows must use binary mode ('rb' / 'wb') to avoid CR/LF translation corrupting the data. Test the cleaned script under a Python interpreter first (for example python kiwi.py -v -d <DVDDIR>) and fix any runtime errors before attempting to bundle. (flylib.com)

Tool choices and tradeoffs (ties to existing replies): suggested py2exe (still an option for Python 2.7 builds) and used IronPython (which can produce a .NET executable using pyc.py, but that exe depends on the .NET runtime and IronPython assemblies). Building with py2exe often fails when Python interpreter bitness doesn’t match the target (use 32‑bit Python on 64‑bit Windows if needed). (stackoverflow.com)

If keeping Python 2.7: either use py2exe or use PyInstaller version 3.6 (the last PyInstaller release that supports Python 2.7). If porting to Python 3 (recommended long term), modern PyInstaller releases are the easiest route (pyinstaller --onefile kiwi.py) but note PyInstaller dropped Python 2 support in v4.0. Also build on Windows (and match the Python bitness to the target environment). (pyinstaller.org)

Licensing and distribution: the source includes a GPL notice — distributing a compiled binary triggers GPL obligations (provide corresponding source or a compliant written offer). See the GPL FAQ for distribution requirements; take ’s copyright note into account. (gnu.org)

Short practical next steps (order): clean HTML entities and binary modes, run the script under Python 2.7 to confirm behavior, choose builder (py2exe or PyInstaller==3.6 for Python 2; modern PyInstaller for Python 3), build on a Windows machine with matching bitness, and include GPL source/notice with any distributed binaries.

Recommended Answers

All 5 Replies

I did try and it came up with a few errors and I have no clue what to do. Thanks.

I was able to compile it with IronPython's compiler, so I can give you that, if you don't mind it running on .NET of course.

could you send me a link to the program that runs on the NET
thanks

You need to observe the line:
Copyright 2009 Bert Vermeulen <>

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.