Cannot write to text file python 2.7 invalid syntax? - python

My code works perfectly, but I want it to write the values to a text file. When I try to do it, I get 'invalid syntax'. When I use a python shell, it works. So I don't understand why it isn't working in my script.
I bet it's something silly, but why wont it output the data to a text file??
#!/usr/bin/env python
#standard module, needed as we deal with command line args
import sys
from fractions import Fraction
import pyexiv2
#checking whether we got enough args, if not, tell how to use, and exits
#if len(sys.argv) != 2 :
# print "incorrect argument, usage: " + sys.argv[0] + ' <filename>'
# sys.exit(1)
#so the argument seems to be ok, we use it as an imagefile
imagefilename = sys.argv[1]
#trying to catch the exceptions in case of problem with the file reading
try:
metadata = pyexiv2.metadata.ImageMetadata(imagefilename)
metadata.read();
#trying to catch the exceptions in case of problem with the GPS data reading
try:
latitude = metadata.__getitem__("Exif.GPSInfo.GPSLatitude")
latitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLatitudeRef")
longitude = metadata.__getitem__("Exif.GPSInfo.GPSLongitude")
longitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLongitudeRef")
# get the value of the tag, and make it float number
alt = float(metadata.__getitem__("Exif.GPSInfo.GPSAltitude").value)
# get human readable values
latitude = str(latitude).split("=")[1][1:-1].split(" ");
latitude = map(lambda f: str(float(Fraction(f))), latitude)
latitude = latitude[0] + u"\u00b0" + latitude[1] + "'" + latitude[2] + '"' + " " + str(latitudeRef).split("=")[1][1:-1]
longitude = str(longitude).split("=")[1][1:-1].split(" ");
longitude = map(lambda f: str(float(Fraction(f))), longitude)
longitude = longitude[0] + u"\u00b0" + longitude[1] + "'" + longitude[2] + '"' + " " + str(longitudeRef).split("=")[1][1:-1]
## Printing out, might need to be modified if other format needed
## i just simple put tabs here to make nice columns
print " \n A text file has been created with the following information \n"
print "GPS EXIF data for " + imagefilename
print "Latitude:\t" + latitude
print "Longitude:\t" + longitude
print "Altitude:\t" + str(alt) + " m"
except Exception, e: # complain if the GPS reading went wrong, and print the exception
print "Missing GPS info for " + imagefilename
print e
# Create a new file or **overwrite an existing file**
text_file = open('textfile.txt', 'w')
text_file.write("Latitude" + latitude)
# Close the output file
text_file.close()
except Exception, e: # complain if the GPS reading went wrong, and print the exception
print "Error processing image " + imagefilename
print e;
The error I see says:
text_file = open('textfile.txt','w')
^
SyntaxError: invalid syntax

File open is within the first try block. It is outside the second try except block. Move it outside the first try except block or increase the indent to include them within the first try block. It should work fine there.
Also move(increase the indent) the two print statements within the try as well.
This will work for you:
#!/usr/bin/env python
#standard module, needed as we deal with command line args
import sys
from fractions import Fraction
import pyexiv2
#checking whether we got enough args, if not, tell how to use, and exits
#if len(sys.argv) != 2 :
# print "incorrect argument, usage: " + sys.argv[0] + ' <filename>'
# sys.exit(1)
#so the argument seems to be ok, we use it as an imagefile
imagefilename = sys.argv[1]
#trying to catch the exceptions in case of problem with the file reading
try:
metadata = pyexiv2.metadata.ImageMetadata(imagefilename)
metadata.read();
#trying to catch the exceptions in case of problem with the GPS data reading
try:
latitude = metadata.__getitem__("Exif.GPSInfo.GPSLatitude")
latitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLatitudeRef")
longitude = metadata.__getitem__("Exif.GPSInfo.GPSLongitude")
longitudeRef = metadata.__getitem__("Exif.GPSInfo.GPSLongitudeRef")
# get the value of the tag, and make it float number
alt = float(metadata.__getitem__("Exif.GPSInfo.GPSAltitude").value)
# get human readable values
latitude = str(latitude).split("=")[1][1:-1].split(" ");
latitude = map(lambda f: str(float(Fraction(f))), latitude)
latitude = latitude[0] + u"\u00b0" + latitude[1] + "'" + latitude[2] + '"' + " " + str(latitudeRef).split("=")[1][1:-1]
longitude = str(longitude).split("=")[1][1:-1].split(" ");
longitude = map(lambda f: str(float(Fraction(f))), longitude)
longitude = longitude[0] + u"\u00b0" + longitude[1] + "'" + longitude[2] + '"' + " " + str(longitudeRef).split("=")[1][1:-1]
## Printing out, might need to be modified if other format needed
## i just simple put tabs here to make nice columns
print " \n A text file has been created with the following information \n"
print "GPS EXIF data for " + imagefilename
print "Latitude:\t" + latitude
print "Longitude:\t" + longitude
print "Altitude:\t" + str(alt) + " m"
except Exception, e: # complain if the GPS reading went wrong, and print the exception
print "Missing GPS info for " + imagefilename
print e
# Create a new file or **overwrite an existing file**
text_file = open('textfile.txt', 'w')
text_file.write("Latitude" + latitude)
# Close the output file
text_file.close()
except Exception, e: # complain if the GPS reading went wrong, and print the exception
print "Error processing image " + imagefilename
print e;

Can be you are tabulating wrong?... The lines:
print " \n A text file has been created with the following information \n"
print "GPS EXIF data for " + imagefilename
appears to be wrong tabulated
EDIT: The code you posted -the one of the trace- is wrong tabulated, too.

Related

Python except Error handling doesn't display the text and error I tell it to, just crashes and displays weird lines?

Just some background info, this code has another python file which tests my code to see if it works correctly and handles all cases correctly as it's a university code/site.
I'm trying to write to a csv file and display this error if the code that tests it cant find the file:
"Error writing: the error"
My code and output can be shown in the image along with the expected output that the idle/lecturer expexts.
Any ideas on why my code displays the things it does and how I can get it to become the same as the expected output please?
import csv
def rememberInfo():
name = input("What is your name?")
print()
age = input("How old are you?")
print()
course = input("What course are you on?")
print()
location = input("Where do you live?")
print()
try:
with open('employee_file.csv', mode='w') as employee_file:
employee_writer = csv.writer(employee_file, delimiter=',')
employee_writer.writerow([name, age, course, location])
line = name + "," + age + "," + course + "," + location
print(line)
employee_file.close()
except Exception as e:
print("Error writing:", e)
if __name__ == "__main__":
rememberInfo()

File read and write adds extra last number

I wrote a quick and sloppy python script for my dad in order to read in text files from a given folder and replace the top lines with a specific format. My apologies for any mix of pluses (+) and commas (,). The purpose was to replace something like this:
Sounding: BASF CPT-1
Depth: 1.05 meter(s)
with something like this:
Tempo(ms); Amplitude(cm/s) Valores provisorios da Sismica; Profundidade[m] = 1.05
I thought I had gotten it all resolved until my dad mentioned that all the text files had the last number repeated in a new line. Here are some examples of output:
output sample links - not enough reputation to post more than 2 links, sorry
Here is my code:
TIME AMPLITUDE
(ms)
#imports
import glob, inspect, os, re
from sys import argv
#work
is_correct = False
succeeded = 0
failed = 0
while not is_correct:
print "Please type the folder name: "
folder_name = raw_input()
full_path = os.path.dirname(os.path.abspath(__file__)) + "\\" + folder_name + "\\"
print "---------Looking in the following folder: " + full_path
print "Is this correct? (Y/N)"
confirm_answer = raw_input()
if confirm_answer == 'Y':
is_correct = True
else:
is_correct = False
files_list = glob.glob(full_path + "\*.txt")
print "Files found: ", files_list
for file_name in files_list:
new_header = "Tempo(ms); Amplitude(cm/s) Valores provisorios da Sismica; Profundidade[m] ="
current_file = open(file_name, "r+")
print "---------Looking at: " + current_file.name
file_data = current_file.read()
current_file.close()
match = re.search("Depth:\W(.+)\Wmeter", file_data)
if match:
new_header = new_header + str(match.groups(1)[0]) + "\n"
print "Depth captured: ", match.groups()
print "New header to be added: ", new_header
else:
print "Match failed!"
match_replace = re.search("(Sounding.+\s+Depth:.+\s+TIME\s+AMPLITUDE\s+.+\s+) \d", file_data)
if match_replace:
print "Replacing text ..."
text_to_replace = match_replace.group(1)
print "SANITY CHECK - Text found: ", text_to_replace
new_data = file_data.replace(text_to_replace, new_header)
current_file = open(file_name, "r+")
current_file.write(new_data)
current_file.close()
succeeded = succeeded + 1
else:
print "Text not found!"
failed = failed + 1
# this was added after I noticed the mysterious repeated number (quick fix)
# why do I need this?
lines = file(file_name, 'r').readlines()
del lines[-1]
file(file_name, 'w').writelines(lines)
print "--------------------------------"
print "RESULTS"
print "--------------------------------"
print "Succeeded: " , succeeded
print "Failed: ", failed
#template -- new_data = file_data.replace("Sounding: BASF CPT-1\nDepth: 29.92 meter(s)\nTIME AMPLITUDE \n(ms)\n\n")
What am I doing wrong exactly? I am not sure why the extra number is being added at the end (as you can see on the "modified text file - broken" link above). I'm sure it is something simple, but I am not seeing it. If you want to replicate the broken output, you just need to comment out these lines:
lines = file(file_name, 'r').readlines()
del lines[-1]
file(file_name, 'w').writelines(lines)
The problem is that, when you go to write your new data to the file, you are opening the file in mode r+, which means "open the file for reading and writing, and start at the beginning". Your code then writes data into the file starting at the beginning. However, your new data is shorter than the data already in the file, and since the file isn't getting truncated, that extra bit of data is left over at the end of the file.
Quick solution: in your if match_replace: section, change this line:
current_file = open(file_name, "r+")
to this:
current_file = open(file_name, "w")
This will open the file in write mode, and will truncate the file before you write to it. I just tested it, and it works fine.

Python export to file via ofile without bracket characters

I successfully simplified a python module that imports data from a spectrometer
(I'm a total beginner, somebody else wrote the model of the code for me...)
I only have one problem: half of the output data (in a .csv file) is surrounded by brackets: []
I would like the file to contain a structure like this:
name, wavelength, measurement
i.e
a,400,0.34
a,410,0.65
...
but what I get is:
a,400,[0.34]
a,410,[0.65]
...
Is there any simple fix for this?
Is it because measurement is a string?
Thank you
import serial # requires pyserial library
ser = serial.Serial(0)
ofile = file( 'spectral_data.csv', 'ab')
while True:
name = raw_input("Pigment name [Q to finish]: ")
if name == "Q":
print "bye bye!"
ofile.close()
break
first = True
while True:
line = ser.readline()
if first:
print " Data incoming..."
first = False
split = line.split()
if 10 <= len(split):
try:
wavelength = int(split[0])
measurement = [float(split[i]) for i in [6]]
ofile.write(str(name) + "," + str(wavelength) + "," + str(measurement) + '\n')
except ValueError:
pass # handles the table heading
if line[:3] == "110":
break
print " Data gathered."
ofile.write('\n')
do this:
measurement = [float(split[i]) for i in [6]]
ofile.write(str(name) + "," + str(wavelength) + "," + ",".join(measurement) + '\n')
OR
ofile.write(str(name) + "," + str(wavelength) + "," + split[6] + '\n')

Multiple types in the same line of output

My goal is the last print line in the code but i cant really because i keep getting this error TypeError: unsupported operand type(s) for +: 'int' and 'str'. Is there a quick way to change only the output part to make that possible? I still need them converted to int in the first place but in the case of this output i need to have the words "Population" and "Area" next to ints!
def _demo_fileopenbox():
msg = "Pick A File!"
msg2 = "Select a country to learn more about!"
title = "Open files"
default="*.py"
f = fileopenbox(msg,title,default=default)
writeln("You chose to open file: %s" % f)
countries = {}
with open(f,'r') as handle:
reader = csv.reader(handle, delimiter = '\t')
for row in reader:
countries[row[0]] = int(row[1].replace(',', '')), int(row[2].replace(',', ''))
reply = choicebox(msg=msg2, choices= list(countries.keys()) )
print(reply)
print((countries[reply])[0])
print((countries[reply])[1])
#print(reply + "- \tArea: + " + (countries[reply])[0] + "\tPopulation: " + (countries[reply])[1] )
You'd have to convert them to strings with str():
print(reply + "- \tArea: " + str(countries[reply][0]) + "\tPopulation: " + str(countries[reply][1]))
Or pass them in as arguments and let print take care of it:
print(reply + "- \tArea:", countries[reply][0] + "\tPopulation:", countries[reply][1])
Although at this point, I would use string formatting:
print('{}- \tArea: {}\tPopulation: {}'.format(reply, rountries[reply][0], rountries[reply][1]))
Or you could use the '%' symbol to tell the print line that you are using strings:
print(reply + "- \tArea: %s" % countries[reply][0] + "\tPopulation: %s" + % countries[reply][1])
Python3 recommends using {:s} in place of %s though. May seem daunting at first, but its not too bad and can be useful.
print("{reply}-\tArea: {area}\tPopulation: {population}".format(reply=reply,area=countries[reply][0],population=countries[reply][1]))

Extract specific entries from blastx output file, write to new file

I have created a script that successfully searches for keywords (specified by user) within a Blastx output file in XML format. Now, I need to write those records (query, hit, score, evalue, etc) that contain the keyword in the alignment title to a new file.
I have created separate lists for each of the query titles, hit title, e-value and alignment lengths but cannot seem to write them to a new file.
Problem #1: what if Python errors, and one of the lists is missing a value...? Then all the other lists will be giving wrong information in reference to the query ("line slippage", if you will...).
Problem #2: even if Python doesn't error, and all the lists are the same length, how can I write them to a file so that the first item in each list is associated with each other (and thus, item #10 from each list is also associated?) Should I create a dictionary instead?
Problem#3: dictionaries have only a single value for a key, what if my query has several different hits? Not sure if it will be overwritten or skipped, or if it will just error. Any suggestions? My current script:
from Bio.Blast import NCBIWWW
from Bio.Blast import NCBIXML
import re
#obtain full path to blast output file (*.xml)
outfile = input("Full path to Blast output file (XML format only): ")
#obtain string to search for
search_string = input("String to search for: ")
#open the output file
result_handle = open(outfile)
#parse the blast record
blast_records = NCBIXML.parse(result_handle)
#initialize lists
query_list=[]
hit_list=[]
expect_list=[]
length_list=[]
#create 'for loop' that loops through each HIGH SCORING PAIR in each ALIGNMENT from each RECORD
for record in blast_records:
for alignment in record.alignments: #for description in record.descriptions???
for hsp in alignment.hsps: #for title in description.title???
#search for designated string
search = re.search(search_string, alignment.title)
#if search comes up with nothing, end
if search is None:
print ("Search string not found.")
break
#if search comes up with something, add it to a list of entries that match search string
else:
#option to include an 'exception' (if it finds keyword then DOES NOT add that entry to list)
if search is "trichomonas" or "entamoeba" or "arabidopsis":
print ("found exception.")
break
else:
query_list.append(record.query)
hit_list.append(alignment.title)
expect_list.append(expect_val)
length_list.append(length)
#explicitly convert 'variables' ['int' object or 'float'] to strings
length = str(alignment.length)
expect_val = str(hsp.expect)
#print ("\nquery name: " + record.query)
#print ("alignment title: " + alignment.title)
#print ("alignment length: " + length)
#print ("expect value: " + expect_val)
#print ("\n***Alignment***\n")
#print (hsp.query)
#print (hsp.match)
#print (hsp.sbjct + "\n\n")
if query_len is not hit_len is not expect_len is not length_len:
print ("list lengths don't match!")
break
else:
qrylen = len(query_list)
query_len = str(qrylen)
hitlen = len(hit_list)
hit_len = str(hitlen)
expectlen = len(expect_list)
expect_len = str(expectlen)
lengthlen = len(length_list)
length_len = str(lengthlen)
outpath = str(outfile)
#create new file
outfile = open("__Blast_Parse_Search.txt", "w")
outfile.write("File contains entries from [" + outpath + "] that contain [" + search_string + "]")
outfile.close
#write list to file
i = 0
list_len = int(query_len)
for i in range(0, list_len):
#append new file
outfile = open("__Blast_Parse_Search.txt", "a")
outfile.writelines(query_list + hit_list + expect_list + length_list)
i = i + 1
#write to disk, close file
outfile.flush()
outfile.close
print ("query list length " + query_len)
print ("hit list length " + hit_len)
print ("expect list length " + expect_len)
print ("length list length " + length_len + "\n\n")
print ("first record: " + query_list[0] + " " + hit_list[0] + " " + expect_list[0] + " " + length_list[0])
print ("last record: " + query_list[-1] + " " + hit_list[-1] + " " + expect_list[-1] + " " + length_list[-1])
print ("\nFinished.\n")
If I understand your problem correctly you could use a default value for the line slippage thing like:
try:
x(list)
except exception:
append_default_value(list)
http://docs.python.org/tutorial/errors.html#handling-exceptions
or use tuples for dictionary keys like (0,1,1) and use the get method for your default value.
http://docs.python.org/py3k/library/stdtypes.html#mapping-types-dict
If you need to maintain data structures in your output files you might try using shelve:
or you could append some type of reference after each record and give each record a unique id for example '#32{somekey:value}#21#22#44#'
again you can have multiple keys using a tuple.
I don't know if that helps, you might clarify exactly what parts of your code you have trouble with. Like x() gives me output y but I expect z.

Categories

Resources