I am writing a script to take a csv file and write each line of the csv into a placemark in kml. The script works up until the second for loop and it fails to write the placemarks in the kml file. I know the script works fine up to writing the LookAt and then appears to jump over the for loop.
A little background... The csv contains 7 columns and the last column looks like this ";latitude;longitude;radius". That is why I have the first for loop to split out those three bits of information.
Here is what I have so far.
import csv
from Tkinter import *
from tkFileDialog import *
root = Tk()
root.fileName = askopenfilename( filetypes = ( ("Comma Separated Values", "*.csv"), ("All files", "*.*") ) )
print (root.fileName)
#close tkinter gui window
root.destroy()
#open the csv file
data = csv.reader(open (root.fileName), delimiter = ',')
#skip header row
next(data)
for line in data:
raw_coordinates = line[6]
#print raw_coordinates
lat_long_radius = raw_coordinates.split(';')
#Open the file to be written.
f = open('TPS_Report.kml', 'w')
#Writing the kml file.
f.write("<?xml version='1.0' encoding='UTF-8'?>\n")
f.write("<kml xmlns='http://earth.google.com/kml/2.1'>\n")
f.write("<Document>\n")
f.write(" <name>" + str("TPS_Report") + '.kml' +"</name>\n") # display name of kml file in Google Earth
#Create LookAt for start location at 39,-98 4200km eye alt, 0 tilt
print ("Creating LookAt")
f.write(" <LookAt>\n")
f.write(" <longitude>" + str("-98") + "</longitude>\n")
f.write(" <latitude>" + str("39") + "</latitude>\n")
f.write(" <range>" + str("4200000") + "</range>\n")
f.write(" <tilt>" + str("0") + "</tilt>\n")
f.write(" </LookAt>\n")
for row in data:
f.write(" <Placemark>\n")
f.write(" <name>" + lat_long_radius[3] + " meters" + "</name>\n")
f.write(" <description>" + str(row[0]) + "\n")
f.write(" " + str(row[1]) + "\n")
f.write(" " + str(row[2]) + "\n")
f.write(" " + str(row[3]) + "\n")
f.write(" " + str(row[4]) + "\n")
f.write(" " + str(row[5]) + "\n")
f.write(" " + str(row[6]) + "</description>\n")
f.write(" <gx:balloonVisibility>" + str("1") + "</gx:balloonVisibility>\n")
f.write(" <Point>\n")
f.write(" <coordinates>" + lat_long_radius[2] + "," + lat_long_radius[1] + "," + str(0) + "</coordinates>\n")
f.write(" </Point>\n")
f.write(" </Placemark>\n")
f.write("</Document>\n")
f.write("</kml>\n")
f.close()
print ("File Created. ")
print ("Press ENTER to exit. ")
raw_input()
Any help would be appreciated
Your data variable is not a list, it is an iterator that consumes your file. Once you iterate over it, you have reached the end of the file, and any attempt to iterate over it again will fail (as there is nothing more to read).
If you really need to iterate over your file twice, save the contents somewhere (in a list, for example). Or restructure your program so you do everything you need in only one pass.
Your code has also other problems, such as lat_long_radius, which is the same value for all points.
Related
I am trying to convert all csv files in a folder to XML but having issues, code as follows:
import glob
import csv
fileCount = 0
path = "csvs\*.csv"
for fname in glob.glob(path):
print(fname)
for fname in glob.glob(path):
csvFile = fname
xmlFile = "csvs\myData" + str(fileCount) + ".xml"
print (xmlFile)
print (csvFile)
print (fileCount)
fileCount +=1
csvData = csv.reader(open(csvFile))
xmlData = open(xmlFile, 'w')
xmlData.write('<?xml version="1.0" encoding="UTF-8"?>' + "\n")
# there must be only one top-level tag
xmlData.write('<userforms>' + "\n")
rowNum = 0
for row in csvData:
if rowNum == 0:
tags = row
# replace spaces w/ underscores in tag names
for i in range(len(tags)):
tags[i] = tags[i].replace(' ', ' ')
else:
xmlData.write('<userform>' + "\n")
for i in range(len(tags)):
xmlData.write('<response>' + "\n" + ' <field>' + tags[i] + '</field>' + "\n" + ' <value>' + row[i] + '</value>'+ "\n" + '</response>' + "\n")
xmlData.write('</userform>' + "\n")
rowNum +=1
#print (fileCount)
#print (xmlFile)
#print (csvFile)
xmlData.write('</userforms>' + "\n")
#xmlData.write('</csv_data>' + "\n")
xmlData.close()
There are 4 csv files in the original folder, the content of each is the same but the names are 1.csv, 2.csv, 3.csv and 4.csv. This code does generate 4 xml files but the first three are incomplete with just the xml header created.
Is there abyway to add a delay/check to a for loop to ensure it completes?
Console output is clean with only print info available:
csvs\myData0.xml
csvs\1.csv
0
csvs\myData1.xml
csvs\2.csv
1
csvs\myData2.xml
csvs\3.csv
2
csvs\myData3.xml
csvs\4.csv
3
After packing my program I decided to test it out to make sure it worked, a few things happened, but the main issue is with the Save_File.
I use a Save_File.py for data, static save data. However, the frozen python file can't do anything with this file. It can't write to it, or read from it. Writing says saved successful but on load it resets all values to zero again.
Is it normal for any .py file to do this?
Is it an issue in pyinstaller?
Bad freeze process?
Or is there some other reason that the frozen file can't write, read, or interact with files not already inside it? (Save_File was frozen inside and doesn't work, but removing it causes errors, similar to if it never existed).
So the exe can't see outside of itself or change within itself...
Edit: Added the most basic version of the save file, but basically, it gets deleted and rewritten a lot.
def save():
with open("Save_file.py", "a") as file:
file.write("healthy = " + str(healthy) + "\n")
file.write("infected = " + str(infected) + "\n")
file.write("zombies = " + str(zombies) + "\n")
file.write("dead = " + str(dead) + "\n")
file.write("cure = " + str(cure) + "\n")
file.write("week = " + str(week) + "\n")
file.write("infectivity = " + str(infectivity) + "\n")
file.write("infectivity_limit = " + str(infectivity_limit) + "\n")
file.write("severity = " + str(severity) + "\n")
file.write("severity_limit = " + str(severity_limit) + "\n")
file.write("lethality = " + str(lethality) + "\n")
file.write("lethality_limit = " + str(lethality_limit) + "\n")
file.write("weekly_infections = " + str(weekly_infections) + "\n")
file.write("dna_points = " + str(dna_points) + "\n")
file.write("burst = " + str(burst) + "\n")
file.write("burst_price = " + str(burst_price) + "\n")
file.write("necrosis = " + str(necrosis) + "\n")
file.write("necrosis_price = " + str(necrosis_price) + "\n")
file.write("water = " + str(water) + "\n")
file.write("water_price = " + str(water_price) + "\n")
file.write("air = " + str(air) + "\n")
file.write("blood = " + str(blood) + "\n")
file.write("saliva = " + str(saliva) + "\n")
file.write("zombify = " + str(zombify) + "\n")
file.write("rise = " + str(rise) + "\n")
file.write("limit = int(" + str(healthy) + " + " + str(infected) + " + " + str(dead) + " + " + str(zombies) + ")\n")
file.write("old = int(1)\n")
Clear.clear()
WordCore.word_corex("SAVING |", "Save completed successfully")
time.sleep(2)
Clear.clear()
player_menu()
it's probably because the frozen version of the file (somewhere in a .zip file) is loaded and never the one you're writing (works when the files aren't frozen)
That's bad practice to:
- have a zillion global variables to hold your persistent data
- generate code in a python file just to evaluate it back again (it's _self-modifying code_).
If you used C or C++ language, would you generate some code to store your data then compile it in your new executable ? would you declare 300 globals? I don't think so.
You'd be better off with json data format and a dictionary for your variables, that would work for frozen or not frozen:
your dictionary would be like:
variables = {"healthy" : True, "zombies" : 345} # and so on
Access your variables:
if variables["healthy"]: # do something
then save function:
import json
def save():
with open("data.txt", "w") as file:
json.dump(variables,file,indent=3)
creates a text file with data like this:
{
"healthy": true,
"zombies": 345
}
and load function (declaring variables as global to avoid creating the same variable, but local only)
def load():
global variables
with open("data.txt", "r") as file:
variables = json.load(file)
I'm trying to write some code that outputs some text to a list. output is a variable that is a string which is the name of the file to be written. However whenever I look at the file nothing is written.
with open(output, 'w') as f:
f.write("Negative numbers mean the empty space was moved to the left and positive numbers means it was moved to the right" + '\n')
if A == True:
the_h = node.h
elif A== False:
the_h = 0
f.write("Start " + str(node.cargo) + " " + str(node.f) +" " +str(the_h)+" " + '\n')
if flag == 0:
flag = len(final_solution)
for i in range (1,flag):
node = final_solution[i]
f.write(str(node.e_point - node.parent.e_point) + str(node.cargo) + " " + str(node.f) +'\n')
f.close()
Program looks ok, check if the output is set ok, I set as a dummy filename, it worked, presuming code within the block after open has no compiler/interpreter error. The output file should be in the same directory where the source is.
output = "aa.txt"
with open(output, 'w') as f:
f.write("Negative numbers mean the empty space was moved to the left and positive numbers means it was moved to the right" + '\n')
if A == True:
the_h = node.h
elif A== False:
the_h = 0
f.write("Start " + str(node.cargo) + " " + str(node.f) +" " +str(the_h)+" " + '\n')
if flag == 0:
flag = len(final_solution)
for i in range (1,flag):
node = final_solution[i]
f.write(str(node.e_point - node.parent.e_point) + str(node.cargo) + " " + str(node.f) +'\n')
f.close()
You should not add f.close(), as the with statement will do it for you. Also ensure you don't reopen the file elsewhere with open(output, 'w') as that will erase the file.
I am currently trying to save scores from a quiz to an excel sheet which allows the user to read the files, but how can I use their save data to only save the last 3 scores of a user. I understand this would mean reading from the file to see the scores and then making it read how many tries the user has had etc. but I can't quite figure out how to make it so the program will only save the last 3 scores from that user or their 3 highest scores. Thank you.
if pclass == 1:
inFile = open("ascores.csv", 'a')
inFile.write("\n" + pname + ", " + str(correct) + ", " + str(round(etime, 1)))
inFile.close()
inFile = open("ascores.csv", 'r')
print(inFile.read())
elif pclass == 2:
inFile = open("bscores.csv", 'a')
inFile.write("\n" + pname + ", " + str(correct) + ", " + str(round(etime, 1)))
inFile.close()
inFile = open("bscores.csv", 'r')
print(inFile.read())
elif pclass == 3:
inFile = open("cscores.csv", 'a')
inFile.write("\n" + pname + ", " + str(correct) + ", " + str(round(etime, 1)))
inFile.close()
inFile = open("cscores.csv", 'r')
print(inFile.read(sorted(reader, key=lambda row: int(row[0]))))
else:
print("Sorry we can not save your data as the class you entered is 1, 2 or 3.")
You are closing the file before reading its contents.
if pclass == 1:
inFile = open("ascores.csv", 'a')
inFile.write("\n" + pname + ", " + str(correct) + ", " + str(round(etime, 1)))
content = inFile.read()
inFile.close()
inFile = open("ascores.csv", 'r')
print(content)
or more concise:
if pclass == 1:
new_score = "\n" + pname + ", " + str(correct) + ", " + str(round(etime, 1))
with open("ascores.csv", 'a') as in_file:
in_file.write(new_score)
content = in_file.read()
print(content)
Using the with statement will close the file for you.
You can edit the long new_score = "\n" + pname + ", " + str(correct) + ", " + str(round(etime, 1)) to:
new_score = "\n {}, {}, {:.1f}".format(pname, correct, etime)
see: https://docs.python.org/3.4/library/string.html#format-specification-mini-language for an explanation about string formatting.
You could also simplify your code (never repeat yourself):
def saveScore(pname, correct, etime, pclass):
score_files = {1:"ascores.csv", 2:"bscores.csv", 3:"cscores.csv"}
try:
filename = score_files[pclass]
new_score = "\n {}, {}, {:.1f}".format(pname, correct, etime)
with open(filename, 'a') as in_file:
in_file.write(new_score)
content = in_file.read()
return content
except KeyError:
return None
print(saveScore(pname, correct, etime, pclass))
I created a text file that contains in the first line a counter of created users and the rest of the lines the text contains user name, password..
for example:
2
username Name Last_name Password
username1 Name Last_name1 Password1
I'm using the following commands:
def SaveDatA(self):
#if self.CheckValid() == False:
#return
with open("data.txt","a") as f:
f.write(self.userEntry.get() + " " + self.NameEntry.get() + " " + self.LastEntry.get()+ " " + self.PasswordEntry.get() + "\n")
self.counter += 1
I want to update the counter to the first line
Do you want this?
f1_lines = open('data.txt', 'r').readlines()
with open('data.txt','w') as f:
f.write(self.userEntry.get() + " " + self.NameEntry.get() + " " + self.LastEntry.get()+ " " + self.PasswordEntry.get() + "\n")
self.counter += 1
f1_lines[0]=str(self.counter)+'\n'
f.write(''.join(f1_lines))
With readlines() you create a list contain all of lines in the file so you change the first index of that list with f1_lines[0]=str(self.counter)+'\n' then rewrite it in to the file !
After a lot of trials this code work's:
with open("data.txt","a") as f:
f.write(self.userEntry.get() + " " + self.NameEntry.get() + " " + self.LastEntry.get()+ " " + self.PasswordEntry.get() + "\n")
self.counter += 1
fileCopy = open('data.txt', 'r').readlines()
fileCopy[0] = fileCopy[0][1:]
with open("data.txt","w") as f:
f.write(str(self.counter)+" ")
f.write("".join(fileCopy))
but maybe there is another better way ?