def read_contents(self,filename):
with open(filename,'r') as f:
lines=f.read().splitlines()
print lines
s=read_contents('input.txt')
When trying to run this program the error is thrown as two arguments required and self needs to be present as one of the arguments (this is part of a bigger code)
how do i pass filename as arguments without getting error
You must use it within a class:
class Test:
def read_contents(self, filename):
with open(filename, 'r') as f:
lines = f.read().splitlines()
print lines
test = Test()
s = test.read_contents('input.txt')
Or remove the self:
def read_contents(filename):
with open(filename, 'r') as f:
lines = f.read().splitlines()
print lines
s = read_contents('input.txt')
Related
I am trying to replace text value as below. I have 2 text file
1 - input.txt
abc = 123
xyz = 456
pqr = 789
2 - content.txt
AAA = abc
XXX = xyz
PPP = pqr
now I need to read the input.txt file and replace value on content.txt file with input.txt values and get the below output file.
3 - new.txt
AAA = 123
XXX = 456
PPP = 789
How can I do this ?
First read the contents of the file into 2 arrays in the following way
file1handle = open('filename1', 'r')
file1 = file1handle.readlines()
file2handle = open('filename2', 'r')
file2 = file2handle.readlines()
file2handle.close()
file2handle.close()
Then iterate over the contents and try finding the match with variable names and assignments and put the values into third array in following way
for item in file1:
name, value = item.split(' = ')
for item2 in file2:
name2, assignment = item2.split(' = ')
#Here we are trying to check which name is to be assigned which value
if assignment == name:
val = name2+'='+value
file3.append(val)
Then write the contents into file in following way
filehandle3 = open('filename3', 'w')
for line in file3:
filehandle3.write(line)
filehandle3.close()
This may help you,
_input = {}
with open('input.txt', 'r') as f:
s = f.read()
_input = dict((a.split(' = ')[0], int(a.split(' = ')[1])) for a in s.split('\n'))
_content = {}
with open('content.txt', 'r') as f:
s = f.read()
_content = dict((a.split(' = ')[0], a.split(' = ')[1]) for a in s.split('\n'))
for key in _content:
_content[key] = _input[_content[key]]
Result:
In [18]: _content
Out[19]: {'AAA': 123, 'PPP': 789, 'XXX': 456}
How about using pandas: It's shorter, easier to read and faster when using large files.
import pandas as pd
import numpy as np
input=pd.read_csv("input.txt",sep="=",header=None,usecols=[1])
content=pd.read_csv("content.txt",sep="=",header=None,usecols=[0])
foo=np.hstack(([content.values,input.values]))
new=pd.DataFrame(foo)
new.to_csv("new.txt",index=False,sep="=",header=None)
import re
class Defs:
def __init__(self, defs_file):
self._defs = {}
with open(defs_file) as df:
line_num = 0
for l in df:
line_num += 1
m = re.match(r'\s*(\w+)\s*=\s*(\S+)\s*', l)
assert m, \
"invalid assignment syntax with \"{}\" at line {}".format(
l.rstrip(), line_num)
self._defs[m.group(1)] = m.group(2)
def __getitem__(self, var):
return self._defs[var]
#property
def dict(self):
return self._defs
class Replacer:
def __init__(self, defs):
self._defs = defs
def replace_with_defs(self, context_file, output_file):
with open(context_file) as context, open(output_file, 'w') as output:
for line in context:
string_repl = re.sub(r'\b(\w+)\b',
lambda m: self._defs.dict.get(m.group(1)) or m.group(1), line)
output.write(string_repl)
def main():
defs = Defs('input.txt')
repl = Replacer(defs)
repl.replace_with_defs('context.txt', 'output.txt')
if __name__ == '__main__':
main()
To describe what's going on above, the Defs class takes a defs_file which is the input.txt assignments and stores them in a dict binding each variable name to the associated value. The Replacer class handles takes a Defs object and uses those to iterate over each line in the context_file i.e. context.txt and replaces any token (assuming the token is a variable name) with the value associated with it, specified within the Defs object, and writes this out to a file output_file i.e. output.txt. If the token doesn't exist in the Defs object as a valid variable name, it defaults to the write the token as is.
I am new to python and am attempting to use this currently nonfunctioning code to extract information between two headers from a text file.
with open('toysystem.txt','r') as f:
start = '<Keywords>'
end = '</Keywords>'
i = 0
lines = f.readlines()
for line in lines:
if line == start:
keywords = lines[i+1]
i += 1
For reference, the text file looks like this:
<Keywords>
GTO
</Keywords>
Any ideas on what might be wrong with the code? Or perhaps a different way to approach this problem?
Thank you!
lines read from file contains newline symbol at the end, so we probably should strip them,
f object is an iterator, so we don't need to use str.readlines method here.
So we can write something like
with open('toysystem.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
for line in f:
if line.rstrip() == start:
break
for line in f:
if line.rstrip() == end:
break
keywords.append(line)
gives us
>>> keywords
['GTO\n']
If you don't need newline at the end of keywords as well – strip them too:
with open('toysystem.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
for line in f:
if line.rstrip() == start:
break
for line in f:
if line.rstrip() == end:
break
keywords.append(line.rstrip())
gives
>>> keywords
['GTO']
But in this case it will be better to create stripped lines generator like
with open('toysystem.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
stripped_lines = (line.rstrip() for line in f)
for line in stripped_lines:
if line == start:
break
for line in stripped_lines:
if line == end:
break
keywords.append(line)
which does the same.
Finally, if you need your lines in the next parts of script, we can use str.readlines and stripped lines generator:
with open('test.txt', 'r') as f:
start = '<Keywords>'
end = '</Keywords>'
keywords = []
lines = f.readlines()
stripped_lines = (line.rstrip() for line in lines)
for line in stripped_lines:
if line.rstrip() == start:
break
for line in stripped_lines:
if line.rstrip() == end:
break
keywords.append(line.rstrip())
gives us
>>> lines
['<Keywords>\n', 'GTO\n', '</Keywords>\n']
>>> keywords
['GTO']
Further reading
file objects,
iterators (including file iterators),
list comprehension,
generator expression
Use Python re module insted and parse it using regex?!
import re
with open('toysystem.txt','r') as f:
contents = f.read()
# will find all the expressions in the file and return a list of values inside the (). You can extend the expression according to your need.
keywords = re.findall(r'\<keywords\>\s*\n*\s*(.*?)\s*\n*\s*\<\/keywords\>')
print(keywords)
from your file it will print
['GTO']
for more about regular expression and python check Tutorialspoint
, For python3 and Python2
Say I have a textfile containing the following:
1:Programming:Adam:0
2:Math:Max:0
3:Engineering:James:0
I am trying to read this textfile as a list, then have a user specify which 0 of a line they want to change to 1, then rewrite the changes made back into textfile.
So for example if a user specifies line 2, I want the 0 in line 2 to be changed to 1 and then save the changes made back onto the textfile.
So far I have the following and I just can't get it to over write it:
class Book_list:
def __init__(self,book_ID,book_title,book_author,availability):
self.book_ID = book_ID
self.book_title = book_title
self.book_author = book_author
self.availability = availability
def __str__(self):
return ('ID: ' + self.book_ID + '\nBook_Title: ' + self.book_title +
'\nBook_author: ' + self.book_author +
'\navailability: ' + self.availability + '\n')
def __getitem__(self,book_ID):
return self.book_ID
def __getitem__(self,availability):
return self.availability
x=str(raw_input('enter line number.'))
with open('database.txt','r') as f:
lines = f.readlines()
library = []
for line in lines:
line = line.strip()
data = line.split(':')
b = Book_list(data[0],data[1],data[2],str(data[3]))
library.append(b)
for i in range (0,len(library)):
if (library[i])[0]==x and (library[i])[3]==0:
(library[i])[3]== '1'
with open('database.txt', 'w') as f:
f.writelines( library )
you can read file and store it in a string. then using split make a list from file:
str='a:b:c'
lst=str.split(':') #lst=['a','b','c']
edit as you like and then join them with .join:
str2=':'.join(lst) #str2='a:b:c'
My current code is as follows but I cannot figure out how to access a text file (e.g "john.txt")
def read_script():
while True:
try:
filename = input('Please Enter Text Name: ')
F = open (filename, 'r')
script - F.read()
F.close()
slist = script.split()
return slist
except OSError:
print ('Oops! That file does not exist! Try spelling it correctly: ')
def pig_english():
letterlist = [i + i[0] for i in read_script()]
ayList = [i + 'ay' for i in letterlist]
delaylist = [i[1:] for i in aylist]
print (delaylist)
read_script()
pig_english()
you want raw_input() and not input(). input() interprets the user input as an object and not a string.
I am trying to parse a file that contains the following
# This is 1st line
# This is 2nd line
ATOM This is 3rd line
ATOM This is 4th line
# This is 5th line
# This is 6th line
I wish to use Python 2.7 to parse the file and append lines up to the line starting with ATOM to a list head_list, the lines starting with ATOM to atom_list and lines after the line containing ATOM to a tail_list.
I want to use the startswith() in Python to match lines that start with ATOM. Below is my code, i am passing counter variable which has the index of the last line in the file which starts with ATOM. yet my output does not seem to be right
#!/usr/bin/python
import sys, os
global counter
def AskForFileName () :
file_name = raw_input('Enter the name of the input file \n')
try:
if not file_name :
print "You did not enter a name !"
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return file_name
def ReadFileContents (file_name) :
#print file_name
file = open(file_name,'r')
file_strings=file.readlines()
return file_strings
def BuildHeadList(all_file_contents) :
head_list=[]
i=0
try :
for line in all_file_contents:
if line.startswith("ATOM") :
break
else :
i=int(i)+1
#print "BuildHeadList :"+str(i)+"\n"
head_list.append(line)
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return head_list
def BuildAtomList(all_file_contents) :
atom_list=[]
i=0
global counter
try :
for i,line in enumerate(all_file_contents):
if line.startswith("ATOM") :
atom_list.append(line)
counter=i
#i=int(i)+1
#print "BuildAtomList :"+str(i)+"\n"
else :
continue
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return atom_list
def BuildTailList(all_file_contents) :
tail_list=[]
i=0
global counter
counter=counter+1
print "Counter value is "+str(counter)
try :
for i,line in enumerate(all_file_contents,counter):
print i
tail_list.append(line)
except :
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
return tail_list
def WriteNewFile(head_list,atom_list,tail_list):
file=open('output.txt', 'w')
#for line in head_list :
# print>>file, line,
#for line in atom_list :
# print>>file, line,
for line in tail_list :
print>>file, line,
file.close()
file_name=AskForFileName()
all_file_contents=ReadFileContents(file_name)
head_list=BuildHeadList(all_file_contents)
atom_list=BuildAtomList(all_file_contents)
tail_list=BuildTailList(all_file_contents )
WriteNewFile(head_list,atom_list,tail_list)
This line:
enumerate(all_file_contents, counter)
Doesn't do what you think it does; it iterates over everything in the lists, but numbers them starting from counter instead of 0. A minimal fix would be:
for i, line in enumerate(all_file_contents):
if i >= counter:
tail_list.append(line)
However, much better would be to not iterate over the whole file three times. In particular, note that tail_list = all_file_contents[counter:] gets the result you want. Additionally, get rid of the global and pass counter around explicitly.
You should also read the style guide.