I have a little trouble with Python. Here is code:
f = open('/path/to/file', 'r')
filedata = f.read()
f.close()
postgres = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL')
dbname = filedata.replace('# DBNAME=DB1', 'DBNAME=DB1')
dbrwuser = filedata.replace('# DBRWUSER="user1"', 'DBRWUSER="user1"')
f = open('/path/to/file', 'w')
f.write(postgres)
f.write(dbname)
f.write(dbrwuser)
f.close()
As you can see I'm trying to read a big file and when I try to replace it it just replaces "Postgres" and it does not make change "dbname, dbrwuser" etc. So I tried to figured it out but couldn't do it.
Any idea or sample?
Thanks.
You make three copies of the input instead of replacing it each time. Use the following:
filedata = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL')
filedata = filedata.replace('# DBNAME=DB1', 'DBNAME=DB1')
filedata = filedata.replace('# DBRWUSER="user1"', 'DBRWUSER="user1"')
...
f.write(filedata)
You can also do it by take all replacement string into a dictonary
import re
repString = {'# DBENGINE=MYSQL': 'DBENGINE=PGSQL', '# DBNAME=DB1': 'DBNAME=DB1', '# DBRWUSER="user1"': 'DBRWUSER="user1"'}
repString = dict((re.escape(k), v) for k, v in repString.iteritems())
pattern = re.compile("|".join(repString.keys()))
filedata = pattern.sub(lambda m: repString[repString.escape(m.group(0))], filedata)
f = open('/path/to/file', 'w')
f.write(filedata)
f.close()
A few suggestions and clarifications:
f.read() reads the entire file. This is probably not a good idea for large files. Instead, use
with open(filename, "r") as f:
for line in f:
# do something with the line
Using with open() also eliminates the need for closing the file afterwards - it's done automatically.
string.replace() returns the entire string with the first argument replaced by the second. Since you make a new variable every time you use replace, the changes only apply to the individual variables. Changes made in postgres will not exist in dbname.
Instead, redefine the variable filedata for every replace to keep the changes and avoid needless copying:
filedata = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL')
filedata = filedata.replace('# DBNAME=DB1', 'DBNAME=DB1')
filedata = filedata.replace('# DBRWUSER="user1"', 'DBRWUSER="user1"')
# at this point, filedata contains all three changes
When you open a file for writing using the w option, the file is overwritten. This means that the file will only contain the contents written by your last write, f.write(dbrwuser). Instead, make your changes and only write once or append to the file instead:
filedata = filedata.replace('# DBENGINE=MYSQL', 'DBENGINE=PGSQL')
...
...
with open('/path/to/file', 'w') as f:
f.write(filedata)
Related
I have a problem with a code in python. I want to read a .txt file. I use the code:
f = open('test.txt', 'r') # We need to re-open the file
data = f.read()
print(data)
I would like to read ONLY the first line from this .txt file. I use
f = open('test.txt', 'r') # We need to re-open the file
data = f.readline(1)
print(data)
But I am seeing that in screen only the first letter of the line is showing.
Could you help me in order to read all the letters of the line ? (I mean to read whole the line of the .txt file)
with open("file.txt") as f:
print(f.readline())
This will open the file using with context block (which will close the file automatically when we are done with it), and read the first line, this will be the same as:
f = open(“file.txt”)
print(f.readline())
f.close()
Your attempt with f.readline(1) won’t work because it the argument is meant for how many characters to print in the file, therefore it will only print the first character.
Second method:
with open("file.txt") as f:
print(f.readlines()[0])
Or you could also do the above which will get a list of lines and print only the first line.
To read the fifth line, use
with open("file.txt") as f:
print(f.readlines()[4])
Or:
with open("file.txt") as f:
lines = []
lines += f.readline()
lines += f.readline()
lines += f.readline()
lines += f.readline()
lines += f.readline()
print(lines[-1])
The -1 represents the last item of the list
Learn more:
with statement
files in python
readline method
Your first try is almost there, you should have done the following:
f = open('my_file.txt', 'r')
line = f.readline()
print(line)
f.close()
A safer approach to read file is:
with open('my_file.txt', 'r') as f:
print(f.readline())
Both ways will print only the first line.
Your error was that you passed 1 to readline which means you want to read size of 1, which is only a single character. please refer to https://www.w3schools.com/python/ref_file_readline.asp
I tried this and it works, after your suggestions:
f = open('test.txt', 'r')
data = f.readlines()[1]
print(data)
Use with open(...) instead:
with open("test.txt") as file:
line = file.readline()
print(line)
Keep f.readline() without parameters.
It will return you first line as a string and move cursor to second line.
Next time you use f.readline() it will return second line and move cursor to the next, etc...
I'm working on a Python project in Visual Studio. I want to process a longer text file, this is a simplified version:
David Tubb
Eduardo Cordero
Sumeeth Chandrashekar
So for reading this file I use this code:
with open("data.txt", "r") as f:
f_contents = f.read()
print(f_contents)
I want to put these items into a new array that looks like that:
['David Tubb','Eduardo Cordero','Sumeeth Chandrashekar']
Is that possible?
Yes, the following code will work for this:
output = [] # the output list
nameFile = open('data.txt', 'r')
for name in nameFile:
# get rid of new line character and add it to your list
output.append(name.rstrip('\n'))
print output
# don't forget to close the file!
nameFile.close()
result = []
with open("data.txt", "r") as f:
result = f.read().splitlines()
print(result)
Output:
['David Tubb', 'Eduardo Cordero', 'Sumeeth Chandrashekar']
The method stated by python for opening a file context is using "with open", this ensures the context will end during clean up.
python.org-pep-0343
dalist = list()
with open('data.txt', 'r') as infile:
for line in infile.readlines():
dalist.append(line)
Additonal resource for contex handeling: https://docs.python.org/3/library/contextlib.html
The following is my replace line function:
def replace_line(file_name, num, replaced):
f = open(file_name, 'r', encoding='utf-8')
lines = f.readlines()
lines[num] = replaced
f.close()
f = open(file_name, 'w', encoding='utf-8')
f.writelines(lines)
f.close()
I am using this following line to run my code:
replace_line('Store.txt', int(line), new)
When I run my code, it replaces that line however it also removes everything after that line. For example, if this was my list:
To be honest, I'm not sure what was wrong with the original function. But I tried redoing it and this seems to work fine:
def replace_line(file_name, line_num, text):
with open(filename, 'r+') as f:
lines = f.read().splitlines()
lines[line_num] = text
f.seek(0)
f.writelines(lines)
f.truncate()
Please note that this overwrites the entire file. If you need to handle large files or are concerned with memory usage, you might want
to try another approach.
I'm trying to figure out how to read a file, find certain substrings, and edit the inputted file to write characters before and after that substring, but i'm stuck. I can only figure out how to write to the end of a file and not in the middle of the file in the middle of a line somewhere!
So for example, say I have a text file:
blah blurh blap
then I have code:
f = open('inputFile.txt', 'r+')
for line in f:
if 'blah' in line:
f.write('!')
f.close()
The way it is written above, the resulting text would say something like:
blah blurh blap!
but I need a way to figure out for it to say:
!blah! blurh blap
and I can't figure it out and can't find anything online about it. Any ideas?
A way to to this, as mentioned in comments, is to write to a different, temp file then renaming it.
This way is less memory expensive, albeit, it will occupy 2x the space in disk for a moment.
import os
with open('inputFile.txt', 'r') as inp, open('outfile.txt', 'w') as out:
for line in inp:
out.write(line.replace('blah', '!blah!'))
# Windows doesn't let you overwrite a file, remove it old input first
os.unlink('inputFile.txt')
os.rename('outfile.txt', 'inputFile.txt')
Or you can load the file entirely in memory, then re-write it.
with open('inputFile.txt', 'r') as inp:
fixed = inp.read().replace('blah', '!blah!')
with open('inputFile.txt', 'w') as out:
out.write(fixed)
Open the file, use replace() to modify the content and save the result to a string. Then you can write the string to your file.
file_name = 'inputFile.txt'
with open(file_name, 'r') as f:
file_content = f.read().replace('blah', '!blah!')
with open(file_name, 'w') as f:
f.write(file_content)
The only way I know to do this sort of thing is to write to a new file and rename it to the old file name at the end. Something like:
def mod_inline(myfilepath):
tmp = os.tmpnam()
with open(tmp,'w') as outfile:
with open(myfilepath, 'r') as infile:
for line in infile:
if 'blah' in line:
outfile.write(line + '!')
else:
outfile.write(line)
os.rename(tmp, myfilepath)
Input = sample.txt
blah blub blur
test hello world
Code - Read the file, operate on the lines, output to same file
filename = 'sample.txt'
# Read the file
with open(filename) as f:
file_lines = f.readlines()
# Operate on the lines
char = '!'
replace = 'blah'
for i,line in enumerate(file_lines):
file_lines[i] = line.replace(replace, '{0}{1}{0}'.format(char, replace))
# Overwrite the file with the new content
with open(filename, "w") as f:
for line in file_lines:
f.write(line)
Output - characters surrounding the string
!blah! blub blur
test hello world
Here's an approach with the re-module, which allows you to be a little more flexible and define multiple substrings to be surrounded by another string.
Code/Demo:
import re
def surround_keysubs(s, ksubs, char):
regex = '|'.join(ksubs)
repl_fun = lambda m: '{}{}{}'.format(char, m.group(), char)
return re.sub(regex, repl_fun, s)
keysubs = {'blah', 'bar'}
char = '!'
with open('testfile') as f:
content = surround_keysubs(f.read(), keysubs, char)
with open('testfile', 'w') as out:
out.write(content)
Demo:
$ cat testfile
blah blurh blap
foo bar buzz
blah blurh blap
$ python surround_keysubs.py
$ cat testfile
!blah! blurh blap
foo !bar! buzz
!blah! blurh blap
How can I insert a string at the beginning of each line in a text file, I have the following code:
f = open('./ampo.txt', 'r+')
with open('./ampo.txt') as infile:
for line in infile:
f.insert(0, 'EDF ')
f.close
I get the following error:
'file' object has no attribute 'insert'
Python comes with batteries included:
import fileinput
import sys
for line in fileinput.input(['./ampo.txt'], inplace=True):
sys.stdout.write('EDF {l}'.format(l=line))
Unlike the solutions already posted, this also preserves file permissions.
You can't modify a file inplace like that. Files do not support insertion. You have to read it all in and then write it all out again.
You can do this line by line if you wish. But in that case you need to write to a temporary file and then replace the original. So, for small enough files, it is just simpler to do it in one go like this:
with open('./ampo.txt', 'r') as f:
lines = f.readlines()
lines = ['EDF '+line for line in lines]
with open('./ampo.txt', 'w') as f:
f.writelines(lines)
Here's a solution where you write to a temporary file and move it into place. You might prefer this version if the file you are rewriting is very large, since it avoids keeping the contents of the file in memory, as versions that involve .read() or .readlines() will. In addition, if there is any error in reading or writing, your original file will be safe:
from shutil import move
from tempfile import NamedTemporaryFile
filename = './ampo.txt'
tmp = NamedTemporaryFile(delete=False)
with open(filename) as finput:
with open(tmp.name, 'w') as ftmp:
for line in finput:
ftmp.write('EDF '+line)
move(tmp.name, filename)
For a file not too big:
with open('./ampo.txt', 'rb+') as f:
x = f.read()
f.seek(0,0)
f.writelines(('EDF ', x.replace('\n','\nEDF ')))
f.truncate()
Note that , IN THEORY, in THIS case (the content is augmented), the f.truncate() may be not really necessary. Because the with statement is supposed to close the file correctly, that is to say, writing an EOF (end of file ) at the end before closing.
That's what I observed on examples.
But I am prudent: I think it's better to put this instruction anyway. For when the content diminishes, the with statement doesn't write an EOF to close correctly the file less far than the preceding initial EOF, hence trailing initial characters remains in the file.
So if the with statement doens't write EOF when the content diminishes, why would it write it when the content augments ?
For a big file, to avoid to put all the content of the file in RAM at once:
import os
def addsomething(filepath, ss):
if filepath.rfind('.') > filepath.rfind(os.sep):
a,_,c = filepath.rpartition('.')
tempi = a + 'temp.' + c
else:
tempi = filepath + 'temp'
with open(filepath, 'rb') as f, open(tempi,'wb') as g:
g.writelines(ss + line for line in f)
os.remove(filepath)
os.rename(tempi,filepath)
addsomething('./ampo.txt','WZE')
f = open('./ampo.txt', 'r')
lines = map(lambda l : 'EDF ' + l, f.readlines())
f.close()
f = open('./ampo.txt', 'w')
map(lambda l : f.write(l), lines)
f.close()