Related
I'm trying to write the text fields values to a file like this (where inputtxt is a Text widget):
input_file_name = inputtxt1.get('1.0', 'end-1c').replace(" ","")
num_of_compare_points = inputtxt2.get('1.0','end-1c')
VER = inputtxt3.get('1.0','end-1c')
mode = inputtxt4.get(1.0','end-1c')
executionMode = inputtxt5.get('1.0','end-1c')
numOfWorkers = inputtxt6.get ('1.0','end-1c')
sessionFile = inputtxt7.get('1.0','end-1c')
file = open("file_1.setup","w")
file.write (input_file_name + "\n" + num_of_compare_points + "\n" + Option+"\n"+VER+"\n"+mode+"\n"+executionMode+"\n"+numOfWorkers+"\n"+sessionFile)
This method was good but I want to write the variable name +the value to the file so that the user can fill the values from the file not only through GUI and the order in file will be irrelevant since we're storing in the variable itself , Example:
File_1.setup:
input_file_name = (some name the user can change it from here not from GUI)
num_of_compare_points = (some number the user can change it from here not from GUI)
.
.
.
etc
UPDATE: I'm using the file attribute:value in a restore finction which put the value of each attribute on its related text field ; the problem here that I have only the value but not the variable:value and the variables must be in order (I need the order to be irrelevent since I'll use the variable name)
def restore_info():
if os.stat('file_1.setup').st_size == 0:
print("Writing to setup file..")
else:
with open('file_1.setup','r') as f:
lines = list(line for line in (l.strip() for l in f) if line)
x = len(lines)
print (x)
for i in lines:
print (i)
if (x==7):
inputtxt1.insert('end',lines[0])
inputtxt2.insert('end',lines[1])
inputtxt3.insert['end',lines[2])
... etc
UPDATE2 : I've managed to split each line based on ":" but I need a way to tell the program where is variable and where is value
def restore_info():
if os.stat('file_1.setup').st_size == 0:
print("Writing to setup file..")
else:
with open('file_1.setup','r') as f:
lines = list(line for line in (l.strip() for l in f) if line)
x = len(lines)
print (x)
for i in lines:
splitted_i=i.split(":")
print (splitted_i)
UPDATE 3:Advantage of this step
User will be able to apply the value manually, and not only through GUI.
The order will be irrelevant.
Any amount of spaces should be allowed around and in between the variable name and its value.
It will be very easy to search file_1.setup and extract the value for each field.
What you need to do is to collect the data into a dict and dump it as key value pair
sessionFile = 'x'
executionMode = 'y'
data = {'sessionFile': sessionFile, 'executionMode': executionMode}
with open('out.txt', 'w') as f:
for k, v in data.items():
f.write(f'{k}:{v}\n')
out.txt
sessionFile:x
executionMode:y
I'm trying to write a code that will take data from a file and write it differently. I have the code for the most part but when i run it, everything is on one line.
import csv
#Step 4
def read_data(filename):
try:
data = open("dna.txt", "r")
except IOError:
print( "File not found")
return data
#Step 5
def get_dna_stats(dna_string):
a_letters = ""
t_letters = ""
if "A" in dna_string:
a_letters.append("A")
if "T" in dna_string:
t_letters.append("T")
nucleotide_content = ((len(a_letters) + len(t_letters))/len(dna_string))
#Step 6
def get_dna_complement(dna_string):
dna_complement = ""
for i in dna_string:
if i == "A":
dna_complement.append("T")
elif i == "T":
dna_complement.append("A")
elif i == "G":
dna_complement.append("C")
elif i == "C":
dna_complement.append("G")
else:
break
return dna_complement
#Step 7
def print_dna(dna_strand):
dna_complement = get_dna_complement(dna_strand)
for i in dna_strand:
for j in dna_complement:
print( i + "=" + j)
#Step 8
def get_rna_sequence(dna_string):
rna_complement = ""
for i in dna_string:
if i == "A":
rna_complement.append("U")
elif i == "T":
rna_complement.append("A")
elif i == "G":
rna_complement.append("C")
elif i == "C":
rna_complement.append("G")
else:
break
return rna_complement
#Step 9
def extract_exon(dna_strand, start, end):
return (f"{dna_strand} between {start} and {end}")
#Step 10
def calculate_exon_pctg(dna_strand, exons):
exons_length = 0
for i in exons:
exons_length += 1
return exons_length/ len(dna_strand)
#Step 11
def format_data(dna_string):
x = "dna_strand"[0:62].upper()
y = "dna_strand"[63:90].lower()
z = "dna_strand"[91:-1].upper()
return x+y+z
#Step 12
def write_results(output, filename):
try:
with open("output.csv","w") as csvFile:
writer = csv.writer(csvFile)
for i in output:
csvFile.write(i)
except IOError:
print("Error writing file")
#Step 13
def main():
read_data("dna.txt")
output = []
output.append("The AT content is" + get_dna_stats() + "% of the DNA sequence.")
get_dna_stats("dna_sequence")
output.append("The DNA complement is " + get_dna_complement())
get_dna_complement("dna_sequence")
output.append("The RNA sequence is" + get_rna_sequence())
get_rna_sequence("dna_sequence")
exon1 = extract_exon("dna_sequence", 0, 62)
exon2 = extract_exon("dna_sequence", 91, len("dna_sequence"))
output.append(f"The exon regions are {exon1} and {exon2}")
output.append("The DNA sequence, which exons in uppercase and introns in lowercase, is" + format_dna())
format_data("dna_sequence")
output.append("Exons comprise " + calculate_exon_pctg())
calculate_exon_pctg("dna_sequence",[exon1, exon2])
write_results(output, "results.txt")
print("DNA processing complete")
#Step 14
if __name__ == "__main__":
main()
When I run it, its supposed to output a file that looks like this but my code ends up putting every word on the top line like this
I have a feeling it has to do with the write_resultsfunction but that's all i know on how to write to the file.
The second mistake I'm making is that I'm not calling the functions correctly in the append statements. I've tried concatenating and I've tried formatting the string but now I'm hitting a road block on what I need to do.
When you write to the file you need to concat a '\n' to the end of the string every time you want to have something on a new line in the written file
for example:
output.append("The AT content is" + get_dna_stats() + "% of the DNA sequence." + '\n')
To solve your second problem I would change your code to something like this:
temp = "The AT content is" + get_dna_stats() + "% of the DNA sequence." + '\n'
output.append(temp)
When you append to a list and call a function it will take the literal text of the function instead of calling it. Doing it with a temp string holder will call the function before the string is concatenated. Then you are able to append the string to the list
read_data() doesn't actually read anything (just opens file). It should read the file and return its contents:
def read_data(filename):
with open(filename, "r") as f:
return f.read()
get_dna_stats() won't get DNA stats (won't return anything, and it doesn't count "A"s or "T"s, only checks if they're present, nucleotide_content is computed but never used or returned. It should probably count and return the results:
def get_dna_stats(dna_string):
num_a = dna_string.count("A")
num_t = dna_string.count("T")
nucleotide_content = (num_a + num_t) /float(len(dna_string))
return nucleotide_content
get_dna_complement() and get_rna_sequence(): you can't append to a string. Instead use
dna_complement += "T"
... and rather than break, you either append a "?" to denote a failed transscription, or raise ValueError("invalid letter in DNA: "+i)
print_dna() is a bit more interesting. I'm guessing you want to "zip" each letter of the DNA and its complement. Coincidentally, you can use the zip function to achieve just that:
def print_dna(dna_strand):
dna_complement = get_dna_complement(dna_strand)
for dna_letter, complement in zip(dna_strand, dna_complement):
print(dna_letter + "=" + complement)
As for extract_exon(), I don't know what that is, but presumably you just want the substring from start to end, which is achieved by:
def extract_exon(dna_strand, start, end):
return dna_strand[start:end] # possibly end+1, I don't know exons
I am guessing that in calculate_exon_pctg(), you want exons_length += len(i) to sum the lengths of the exons. You can achieve this by using the buildin function sum:
exons_length = sum(exons)
In function format_data(), loose the doublequotes. You want the variable.
main() doesn't pass any data around. It should pass the results of read_data() to all the other functions:
def main():
data = read_data("dna.txt")
output = []
output.append("The AT content is " + get_dna_stats(data) + "% of the DNA sequence.")
output.append("The DNA complement is " + get_dna_complement(data))
output.append("The RNA sequence is" + get_rna_sequence(data))
...
write_results(output, "results.txt")
print("DNA processing complete")
The key for you at this stage is to understand how function calls work: they take data as input parameters, and they return some results. You need to a) provide the input data, and b) catch the results.
write_results() - from your screenshot, you seem to want to write a plain old text file, yet you use csv.writer() (which writes CSV, i.e. tabular data). To write plain text,
def write_results(output, filename):
with open(filename, "w") as f:
f.write("\n".join(output)) # join output lines with newline
f.write("\n") # extra newline at file's end
If you really do want a CSV file, you'll need to define the columns first, and make all the output you collect fit that column format.
You never told your program to make a new line. You could either append or prepend the special "\n" character to each of your strings or you could do it in a system agnostic way by doing
import os
at the top of your file and writing your write_results function like this:
def write_results(output, filename):
try:
with open("output.csv","w") as csvFile:
writer = csv.writer(csvFile)
for i in output:
csvFile.write(i)
os.write(csvFile, os.linesep) # Add this line! It is a system agnostic newline
except IOError:
print("Error writing file")
#
# Obtain user input for file name, and open it
#
inFile = open(input("Enter file name: "), "r")
#
# Process data and address possible errors
#
countDinner = 0
countLodging = 0
countConference = 0
valueDinner = 0
valueLodging = 0
valueConference = 0
done = False
while not done :
line = inFile.readline()
try :
s = line
serviceAmount = ';'.join(s.split(';')[1:-1]) #Removes date and name regardless of format
serviceAmount.split(";")
s.lower()
if "dinner" in s :
countDinner = countDinner + 1
valueDinner = valueDinner + int(filter(str.isdigit, s))
print("Dinners: ", countDinner, "Value of Dinner sales: ", valueDinner)
elif "lodging" in s :
countLodging = countLodging + 1
valueLodging = valueLodging + int(filter(str.isdigit, s))
print("Lodging: ", countLodging, "Value of Lodging sales: ", valueLodging)
elif "conference" in s :
countConference = countConference + 1
valueConference = valueConference + int(filter(str.isdigit, s))
print("Conferences: ", countConference, "Value of Conference sales: ", valueConference)
elif line == "" :
done = True
else :
print("Invalid file format.")
except FileNotFoundError :
print("Unable to find file.")
finally :
done = True
inFile.close()
Returns "Invalid file format" even when the document is set up specifically for this code. I'm not getting a syntax error, so I'm not sure whats wrong.
The document contains the text:
John;Lodging;123;050617
Tyler;Conference;123;081497
Taylor;Dinner;453;041798
There are a lot of things you aren't doing quite right here. I tried to not only fix the issue you posted about, but also write some code that should be more clear and easier to use. I left comments to explain things.
# Don't open the file here, just get the file name. We will open in later
fname = input("Enter file name: ")
# I think using dicts is more clearn and organized. Having so many variables I think makes the code messy
counts = {"Dinner": 0,
"Lodging": 0,
"Conference": 0}
values = {"Dinner": 0,
"Lodging": 0,
"Conference": 0}
# Lets try to open the file
try:
with open(fname, 'r') as inFile: # Use "with", this way the file is closed automatically when we are done reading it
for linenum, line in enumerate(inFile): # I want to enumerate each line. If there is an error on a line, we can display the line nmber this way
line = line.lower().split(';')[1:-1] # lets make it all lower case, then split and drop as needed
print(line)
if "dinner" in line :
counts["Dinner"] += 1 # x += 1 is the same as x = x + 1, but cleaner
values["Dinner"] += int(line[1])
print("Dinners: {} Value of Dinner sales: {}".format(counts["Dinner"], values["Dinner"]))
elif "lodging" in line :
counts["Lodging"] += 1
values["Lodging"] += int(line[1])
print("Lodging: {} Value of Dinner sales: {}".format(counts["Lodging"], values["Lodging"]))
elif "conference" in line :
counts["Conference"] += 1
values["Conference"] += int(line[1])
print("Conference: {} Value of Dinner sales: {}".format(counts["Conference"], values["Conference"]))
else :
print("Invalid file format on line {}".format(linenum)) # Here is why we used enumerate in the for loop
except FileNotFoundError:
print("Unable to find file.")
Here is your problem:
serviceAmount = ';'.join(s.split(';')[1:-1]) #Removes date and name regardless of format
serviceAmount.split(";")
You should do:
serviceAmount = ';'.join(s.lower().split(';')[1:-1])
You are checking against lower case strings, but not actually lower casing your input.
It is also important to note that s.lower() doesn't actually change s, it just returns a string where all the letters of s have been switched to lower case. Same thing for split (as in not changing the string its called on, not that it returns a string).
Another problem you are going to run into is getting the numbers from your strings.
int(filter(str.isdigit, s))
Won't work. You can use split again like you did earlier (or just not re-join since you only care about the first element in the comparisons).
int(serviceAmount.split(';')[1])
The last thing is the
finally:
done = True
inFile.close()
finally always runs when exiting a try, meaning that you are always done after each loop (and close the file after you read the first line).
If you remove the finally and add inFile.close() inside the elif line == "" it will close, and set done only when you've reached the end of the file.
It could be done as simple as
categories = {}
filename = input("Enter file name: ")
with open(filename, "r") as file:
name, category, value, date = file.readline().split(";")
if category not in categories:
categories[category] = {"count": 0, "value": 0}
categories[category]["count"] += 1
categories[category]["value"] += int(value)
At the end, you'll have a dict with categories, their count, and value, and also their names are not hard-coded.
I have a function where conversion is a list and filename is the name of the input file. I want to write 5 characters in a line then add a new line and add 5 characters to that line and add a new line until there is nothing to write from the list conversion to the file filename. How can I do that?
From what I think I understand about your question, you may need code that looks like this:
import os
def write_data_file(your_collection, data_file_path):
"""Writes data file from memory to previously specified path."""
the_string = ''
for row in your_collection:
for i, c in enumerate(row):
if i % 5 < 4:
the_string += c
else:
the_string += os.linesep + c
with open(data_file_path, 'w') as df:
df.write(the_string)
my_collection = [
"This is more than five characters",
"This is definately more than five characters",
"NOT",
"NADA"
]
write_data_file(my_collection, '/your/file/path.txt')
Other than that, you may need to clarify what you are asking. This code snippet loops through a collection (like a list) then loops over the assumed string contained at that row in the collection. It adds the new line whenever the 5 character limit has been reached.
def foo(conversion, filename):
with open(filename, "a") as f:
line = ""
for s in conversion:
for c in s:
if len(line) < 5:
line += c
else:
f.write(line + "\n")
line = c
f.write(line)
Convert the list of strings into one large string, then loop through that string five characters at a time and insert "\n" after each iteration of the loop. Then write that to a file. Here's a basic example of what I mean, might need some tweaking but it'll give you the idea:
# concatenate all the strings for simplicity
big_string = ""
for single_string in conversion:
big_string += single_string
# loop through using 5 characters at a time
string_with_newlines = ""
done = False
while not done:
next_five_chars = big_string[:5]
big_string = big_string[5:]
if next_five_chars:
string_with_newlines += next_five_chars + "\n"
else:
done = True
# write it all to file
with open(filename, "w") as your_file:
your_file.write(string_with_newlines)
l = ["one", "two", "three", "four", "five"]
def write(conversion, filename):
string = "".join(conversion)
f = open(filename, "a")
for i in range(5, len(string) + 5, 5):
f.write(string[i-5:i])
f.write("\n")
if __name__ == '__main__':
write(l, "test.txt")
This create a file called "test.txt" with the content:
onetw
othre
efour
onetw
othre
efour
five
I made a function for grouping your list:
import itertools
def group(iterable, n):
gen = (char for substr in iterable for char in substr)
while True:
part = ''.join(itertools.islice(gen, 0, n))
if not part:
break
yield part
Presentation:
>>> l = ['DBTsiQoECGPPo', 'd', 'aDAuehlM', 'FbUnSuMLuEbHe', 'jRvARVZMn', 'SbGCi'
, 'jhI', 'Rpbd', 'uspffRvPiAmbQEoZDFAG', 'RIbHAcbREdqpMDX', 'bqVMrN', 'FtU', 'nu
fWcfjfmAaUtYtwNUBc', 'oZvk', 'EaytqdRkICuxqbPaPulCZlD', 'dVrZdidLeakPT', 'qttRfH
eJJMOlJRMKBM', 'SAiBrdPblHtRGpjpZKuFLGza', 'RxrLgclVavoCmPkhR', 'YuulTYaNTLghUkK
riOicMuUD']
>>> list(group(l, 5))
['DBTsi', 'QoECG', 'PPoda', 'DAueh', 'lMFbU', 'nSuML', 'uEbHe', 'jRvAR', 'VZMnS'
, 'bGCij', 'hIRpb', 'duspf', 'fRvPi', 'AmbQE', 'oZDFA', 'GRIbH', 'AcbRE', 'dqpMD
', 'XbqVM', 'rNFtU', 'nufWc', 'fjfmA', 'aUtYt', 'wNUBc', 'oZvkE', 'aytqd', 'RkIC
u', 'xqbPa', 'PulCZ', 'lDdVr', 'ZdidL', 'eakPT', 'qttRf', 'HeJJM', 'OlJRM', 'KBM
SA', 'iBrdP', 'blHtR', 'GpjpZ', 'KuFLG', 'zaRxr', 'LgclV', 'avoCm', 'PkhRY', 'uu
lTY', 'aNTLg', 'hUkKr', 'iOicM', 'uUD']
>>> '\n'.join(group(l, 5))
'DBTsi\nQoECG\nPPoda\nDAueh\nlMFbU\nnSuML\nuEbHe\njRvAR\nVZMnS\nbGCij\nhIRpb\ndu
spf\nfRvPi\nAmbQE\noZDFA\nGRIbH\nAcbRE\ndqpMD\nXbqVM\nrNFtU\nnufWc\nfjfmA\naUtYt
\nwNUBc\noZvkE\naytqd\nRkICu\nxqbPa\nPulCZ\nlDdVr\nZdidL\neakPT\nqttRf\nHeJJM\nO
lJRM\nKBMSA\niBrdP\nblHtR\nGpjpZ\nKuFLG\nzaRxr\nLgclV\navoCm\nPkhRY\nuulTY\naNTL
g\nhUkKr\niOicM\nuUD'
Write the result of '\n'.join(group(l, 5)) to a file.
I have a file that looks like this
!--------------------------------------------------------------------------DISK
[DISK]
DIRECTION = 'OK'
TYPE = 'normal'
!------------------------------------------------------------------------CAPACITY
[CAPACITY]
code = 0
ID = 110
I want to read sections [DISK] and [CAPACITY].. there will be more sections like these. I want to read the parameters defined under those sections.
I wrote a following code:
file_open = open(myFile,"r")
all_lines = file_open.readlines()
count = len(all_lines)
file_open.close()
my_data = {}
section = None
data = ""
for line in all_lines:
line = line.strip() #remove whitespace
line = line.replace(" ", "")
if len(line) != 0: # remove white spaces between data
if line[0] == "[":
section = line.strip()[1:]
data = ""
if line[0] !="[":
data += line + ","
my_data[section] = [bit for bit in data.split(",") if bit != ""]
print my_data
key = my_data.keys()
print key
Unfortunately I am unable to get those sections and the data under that. Any ideas on this would be helpful.
As others already pointed out, you should be able to use the ConfigParser module.
Nonetheless, if you want to implement the reading/parsing yourself, you should split it up into two parts.
Part 1 would be the parsing at file level: splitting the file up into blocks (in your example you have two blocks: DISK and CAPACITY).
Part 2 would be parsing the blocks itself to get the values.
You know you can ignore the lines starting with !, so let's skip those:
with open('myfile.txt', 'r') as f:
content = [l for l in f.readlines() if not l.startswith('!')]
Next, read the lines into blocks:
def partition_by(l, f):
t = []
for e in l:
if f(e):
if t: yield t
t = []
t.append(e)
yield t
blocks = partition_by(content, lambda l: l.startswith('['))
and finally read in the values for each block:
def parse_block(block):
gen = iter(block)
block_name = next(gen).strip()[1:-1]
splitted = [e.split('=') for e in gen]
values = {t[0].strip(): t[1].strip() for t in splitted if len(t) == 2}
return block_name, values
result = [parse_block(b) for b in blocks]
That's it. Let's have a look at the result:
for section, values in result:
print section, ':'
for k, v in values.items():
print '\t', k, '=', v
output:
DISK :
DIRECTION = 'OK'
TYPE = 'normal'
CAPACITY :
code = 0
ID = 110
Are you able to make a small change to the text file? If you can make it look like this (only changed the comment character):
#--------------------------------------------------------------------------DISK
[DISK]
DIRECTION = 'OK'
TYPE = 'normal'
#------------------------------------------------------------------------CAPACITY
[CAPACITY]
code = 0
ID = 110
Then parsing it is trivial:
from ConfigParser import SafeConfigParser
parser = SafeConfigParser()
parser.read('filename')
And getting data looks like this:
(Pdb) parser
<ConfigParser.SafeConfigParser instance at 0x100468dd0>
(Pdb) parser.get('DISK', 'DIRECTION')
"'OK'"
Edit based on comments:
If you're using <= 2.7, then you're a little SOL.. The only way really would be to subclass ConfigParser and implement a custom _read method. Really, you'd just have to copy/paste everything in Lib/ConfigParser.py and edit the values in line 477 (2.7.3):
if line.strip() == '' or line[0] in '#;': # add new comment characters in the string
However, if you're running 3'ish (not sure what version it was introduced in offhand, I'm running 3.4(dev)), you may be in luck: ConfigParser added the comment_prefixes __init__ param to allow you to customize your prefix:
parser = ConfigParser(comment_prefixes=('#', ';', '!'))
If the file is not big, you can load it and use Regexes to find parts that are of interest to you.