Python script how can it do short - python

I have written a script on a python "icecast server", and I changed some strings in "/etc/icecast2/icecast.xml" like this:
import os,sys,re
def ices2():
changedir=open(pathh + "icecast3.xml", "w")
data=open("/etc/icecast2/icecast.xml").read()
changedir.write(re.sub("<source-password>hackme</source-password>","<source-password>123</source-password>" % x,data))
changedir.close()
ices2()
def ices1():
changedir1=open(pathh + "icecast2.xml", "w")
data=open(pathh + "icecast3.xml").read()
changedir1.write(re.sub("<relay-password>hackme</relay-password>", "<relay-password>123</relay-password>" % x,data))
changedir1.close()
os.remove(pathh + "icecast3.xml")
ices1()
def ices():
changedir2=open("/etc/icecast2/icecast.xml", "w")
data=open(pathh + "icecast2.xml").read()
changedir2.write(re.sub("<admin-password>hackme</admin-password>","<admin-password>123</admin-password>" % x,data))
changedir2.close()
os.remove(pathh + "icecast2.xml")
ices()
...but it's too long for the script. How can I shorten it? I need to do some changes in one file, open it to make changes and close it without any lost data. I know that it can be done in one function, but how to do it I don't know.
I need three changes in one function like this:
def ices():
changedir=open(pathh + "icecast3.xml", "w")
data=open("/etc/icecast2/icecast.xml").read()
changedir.write(re.sub("<source-password>hackme</source-password>","<source-password>123</source-password>",data))
changedir1.write(re.sub("<relay-password>hackme</relay-password>", "<relay-password>123</relay-password>",data))
changedir2.write(re.sub("<admin-password>hackme</admin-password>","<admin-password>123</admin-password>",data))
changedir.close()
i did it in one function and my script short than upper one. But it's wrong i need do it correctly
changedir=open(pathh + "icecast3.xml", "w")
data=open("/etc/icecast2/icecast.xml").read()
Here I create a new file "pathh + "icecast3.xml" (pathh-/home/user/Downloads), but I need to open file:
"/etc/icecast2/icecast.xml"
...read it and write changes to the same file.

All three functions do the same so you can join them into one. This is not complete solution but I think that you could go on from here on your own:
import os,sys,re
def ices(in_path, out_path, remove=False):
changedir = open(out_path, "w")
data = open(in_path, 'r')
changedir.write(re.sub("<source-password>hackme</source-password>","<source-password>123</source-password>" % x,data.read())) # this is wrong as well but I take it as an example
changedir.close()
data.close()
if remove:
os.remove(in_path)
You can call this function with:
ices(base_path + 'icecast2.xml', base_path + 'icecast3.xml', True)
Hints:
it's better to use os.path.join for creating the full paths (as opposed to string concatenation)
look at with statement and cosider using it for increased readability
EDIT (respecting the clarification in comment):
Sorry I missed the different strings in write. You can do it simply like this:
f = open(filename, 'r')
data = f.read()
f.close()
for tag in ['source', 'relay', 'admin']
sub_str = "<{tag_name}>%s</{tag_name}>".format(tag_name=tag+'-password')
data = re.sub(sub_str % 'hackme', sub_str % '123', data)
f = open(filename+'.new', 'w')
f.write(data)
f.close()

Related

Segmentation Fault

I am using python 2.4.4 (old machine, can't do anything about it) on a UNIX machine. I am extremely new to python/programming and have never used a UNIX machine before. This is what I am trying to do:
extract a single sequence from a FASTA file (proteins + nucleotides) to a temporary text file.
Give this temporary file to a program called 'threader'
Append the output from threader (called tempresult.out) to a file called results.out
Remove the temporary file.
Remove the tempresult.out file.
Repeat using the next FASTA sequence.
Here is my code so far:
import os
from itertools import groupby
input_file = open('controls.txt', 'r')
output_file = open('results.out', 'a')
def fasta_parser(fasta_name):
input = fasta_name
parse = (x[1] for x in groupby(input, lambda line: line[0] == ">"))
for header in parse:
header = header.next()[0:].strip()
seq = "\n".join(s.strip() for s in parse.next())
yield (header, '\n', seq)
parsedfile = fasta_parser(input_file)
mylist = list(parsedfile)
index = 0
while index < len(mylist):
temp_file = open('temp.txt', 'a+')
temp_file.write(' '.join(mylist[index]))
os.system('threader' + ' temp.txt' + ' tempresult.out' + ' structures.txt')
os.remove('temp.txt')
f = open('tempresult.out', 'r')
data = str(f.read())
output_file.write(data)
os.remove('tempresult.out')
index +=1
output_file.close()
temp_file.close()
input_file.close()
When I run this script I get the error 'Segmentation Fault'. From what I gather this is to do with me messing with memory I shouldn't be messing with (???). I assume it is something to do with the temporary files but I have no idea how I would get around this.
Any help would be much appreciated!
Thanks!
Update 1:
Threader works fine when I give it the same sequence multiple times like this:
import os
input_file = open('control.txt', 'r')
output_file = open('results.out', 'a')
x=0
while x<3:
os.system('threader' + ' control.txt' + ' tempresult.out' + ' structures.txt')
f = open('tempresult.out', 'r')
data = str(f.read())
output_file.write(data)
os.remove('result.out')
x += 1
output_file.close()
input_file.close()
Update 2: In the event that someone else gets this error. I forgot to close temp.txt before invoking the threader program.

Why does my file show up blank in python?

I'm trying to get my python file to save numbers into a text file, but it always goes blank when I try it. I've done this many times before but it refuses to work this time.
openfile = 'example'
total = 0.5 #another example
totalstr = str(total)
file = open("%s.txt" % (openfile), "w")
file.write(totalstr)
file.close
"file" is a standard Python type. You want to rename things a bit. I'm also assuming "openfile" should be the string filename you want to use. Both answers so far are correct but putting them together gives:
my_file_name = "myfile"
total = 0.5
my_file_handle = open("%s.txt" %(my_file_name), "w")
my_file_handle.write(str(total))
my_file_handle.close()
file is a keyword in python. So,
print '%s' %(file)
prints
<type 'file'>
You should use:
openfile = 'file'
This works for me:
openfile = "file"
total = 0.5
totalstr = str(total)
file = open("%s.txt" % (openfile), "w")
file.write(totalstr)
file.close()
See if you can spot the changes.

Writing user input to a text file in python

Ok here we go, i've been looking at this all day and i'm going crazy, i thought i'd done the hard bit but now i'm stuck. I'm making a highscores list for a game and i've already created a binary file that store the scores and names in order. Now i have to do the same thing but store the scores and names in a text file.
This is the binary file part but i have no idea where to start with using a text file.
def newbinfile():
if not os.path.exists('tops.dat'):
hs_data = []
make_file = open('tops.dat', 'wb')
pickle.dump(hs_data, make_file)
make_file.close
else:
None
def highscore(score, name):
entry = (score, name)
hs_data = open('tops.dat', 'rb')
highsc = pickle.load(hs_data)
hs_data.close()
hs_data = open('tops.dat', 'wb+')
highsc.append(entry)
highsc.sort(reverse=True)
highsc = highsc[:5]
pickle.dump(highsc, hs_data)
hs_data.close()
return highsc
Any help on where to start with this would be appreciated. Thanks
I think you should use the with keywords.
You'll find examples corresponding to what you want to do here.
with open('output.txt', 'w') as f:
for l in ['Hi','there','!']:
f.write(l + '\n')
Start here:
>>> mydata = ['Hello World!', 'Hello World 2!']
>>> myfile = open('testit.txt', 'w')
>>> for line in mydata:
... myfile.write(line + '\n')
...
>>> myfile.close() # Do not forget to close
EDIT :
Once you are familiar with this, use the with keyword, which guaranties the closure when the file handler gets out of scope:
>>> with open('testit.txt', 'w') as myfile:
... for line in mydata:
... myfile.write(line + '\n')
...
Python has built-in methods for writing to files that you can use to write to a text file.
writer = open("filename.txt", 'w+')
# w+ is the flag for overwriting if the file already exists
# a+ is the flag for appending if it already exists
t = (val1, val2) #a tuple of values you want to save
for elem in t:
writer.write(str(elem) + ', ')
writer.write('\n') #the write function doesn't automatically put a new line at the end
writer.close()

python implementation of 'readAsDataURL

i'm having some troubles to get the URI from a certain file, like .mp4/.ogg/etc..
The thing is that i need to do it in python, where the webserver is running.
Initially, i proceed like this:
def __parse64(self, path_file):
string_file = open(path_file, 'r').readlines()
new_string_file = ''
for line in string_file:
striped_line = line.strip()
separated_lines = striped_line.split('\n')
new_line = ''
for l in separated_lines:
new_line += l
new_string_file += new_line
self.encoded_string_file = b64.b64encode(new_string_file)
But this way, doesn't give what i need, if you compare the result with given here.
What a i need is a way to implement the function readAsDataURL() from FileReader class (see the code of the link above), in python.
UPDATE:
The solution given by #SeanVieira, returns a valid data field for the URI.
def __parse64(self, path_file):
file_data = open(path_file, 'rb').read(-1)
self.encoded_string_file = b64.b64encode(file_data)
Now how can i complete the URI, with the previous fields?
Like this.
For example: data:video/mp4;base64,data
Thanks!
The problem is that you are treating binary-encoded data as text data, which is breaking your code.
Try:
def __parse64(self, path_file):
file_data = open(path_file, 'rb').read(-1)
#This slurps the whole file as binary.
self.encoded_string_file = b64.b64encode(file_data)
The #SeanVieria answer will not work if the file is very large (more than 7mb)
This function will work for all cases (tested on Python version 3.4):
def __parse64(self, path_file):
data = bytearray()
with open(path_file, "rb") as f:
b = f.read(1)
while b != b"":
data.append(int.from_bytes(b, byteorder='big'))
b = f.read(1)
self.encoded_string_file = base64.b64encode(data)

Writing string to a file on a new line every time

I want to append a newline to my string every time I call file.write(). What's the easiest way to do this in Python?
Use "\n":
file.write("My String\n")
See the Python manual for reference.
You can do this in two ways:
f.write("text to write\n")
or, depending on your Python version (2 or 3):
print >>f, "text to write" # Python 2.x
print("text to write", file=f) # Python 3.x
You can use:
file.write(your_string + '\n')
If you use it extensively (a lot of written lines), you can subclass 'file':
class cfile(file):
#subclass file to have a more convienient use of writeline
def __init__(self, name, mode = 'r'):
self = file.__init__(self, name, mode)
def wl(self, string):
self.writelines(string + '\n')
Now it offers an additional function wl that does what you want:
with cfile('filename.txt', 'w') as fid:
fid.wl('appends newline charachter')
fid.wl('is written on a new line')
Maybe I am missing something like different newline characters (\n, \r, ...) or that the last line is also terminated with a newline, but it works for me.
you could do:
file.write(your_string + '\n')
as suggested by another answer, but why using string concatenation (slow, error-prone) when you can call file.write twice:
file.write(your_string)
file.write("\n")
note that writes are buffered so it amounts to the same thing.
Another solution that writes from a list using fstring
lines = ['hello','world']
with open('filename.txt', "w") as fhandle:
for line in lines:
fhandle.write(f'{line}\n')
And as a function
def write_list(fname, lines):
with open(fname, "w") as fhandle:
for line in lines:
fhandle.write(f'{line}\n')
write_list('filename.txt', ['hello','world'])
file_path = "/path/to/yourfile.txt"
with open(file_path, 'a') as file:
file.write("This will be added to the next line\n")
or
log_file = open('log.txt', 'a')
log_file.write("This will be added to the next line\n")
Unless write to binary files, use print. Below example good for formatting csv files:
def write_row(file_, *columns):
print(*columns, sep='\t', end='\n', file=file_)
Usage:
PHI = 45
with open('file.csv', 'a+') as f:
write_row(f, 'header', 'phi:', PHI, 'serie no. 2')
write_row(f) # additional empty line
write_row(f, data[0], data[1])
You can also use partial as a more pythonic way of creating this kind of wrappers. In the example below, row is print with predefined kwargs.
from functools import partial
with open('file.csv', 'a+') as f:
row = partial(print, sep='\t', end='\n', file=f)
row('header', 'phi:', PHI, 'serie no. 2', end='\n\n')
row(data[0], data[1])
Notes:
print documentation
'{}, {}'.format(1, 'the_second') - https://pyformat.info/, PEP-3101
'\t' - tab character
*columns in function definition - dispatches any number of arguments to list - see question on *args & **kwargs
Just a note, file isn't supported in Python 3 and was removed. You can do the same with the open built-in function.
f = open('test.txt', 'w')
f.write('test\n')
Ok, here is a safe way of doing it.
with open('example.txt', 'w') as f:
for i in range(10):
f.write(str(i+1))
f.write('\n')
This writes 1 to 10 each number on a new line.
I really didn't want to type \n every single time and #matthause's answer didn't seem to work for me, so I created my own class
class File():
def __init__(self, name, mode='w'):
self.f = open(name, mode, buffering=1)
def write(self, string, newline=True):
if newline:
self.f.write(string + '\n')
else:
self.f.write(string)
And here it is implemented
f = File('console.log')
f.write('This is on the first line')
f.write('This is on the second line', newline=False)
f.write('This is still on the second line')
f.write('This is on the third line')
This should show in the log file as
This is on the first line
This is on the second lineThis is still on the second line
This is on the third line
This is the solution that I came up with trying to solve this problem for myself in order to systematically produce \n's as separators. It writes using a list of strings where each string is one line of the file, however it seems that it may work for you as well. (Python 3.+)
#Takes a list of strings and prints it to a file.
def writeFile(file, strList):
line = 0
lines = []
while line < len(strList):
lines.append(cheekyNew(line) + strList[line])
line += 1
file = open(file, "w")
file.writelines(lines)
file.close()
#Returns "\n" if the int entered isn't zero, otherwise "".
def cheekyNew(line):
if line != 0:
return "\n"
return ""
You can decorate method write in specific place where you need this behavior:
#Changed behavior is localized to single place.
with open('test1.txt', 'w') as file:
def decorate_with_new_line(method):
def decorated(text):
method(f'{text}\n')
return decorated
file.write = decorate_with_new_line(file.write)
file.write('This will be on line 1')
file.write('This will be on line 2')
file.write('This will be on line 3')
#Standard behavior is not affected. No class was modified.
with open('test2.txt', 'w') as file:
file.write('This will be on line 1')
file.write('This will be on line 1')
file.write('This will be on line 1')
Using append (a) with open() on a print() statement looks easier for me:
save_url = ".\test.txt"
your_text = "This will be on line 1"
print(your_text, file=open(save_url, "a+"))
another_text = "This will be on line 2"
print(another_text, file=open(save_url, "a+"))
another_text = "This will be on line 3"
print(another_text, file=open(save_url, "a+"))
You could use C-style string formatting:
file.write("%s\n" % "myString")
More about String Formatting.
If write is a callback, you may need a custom writeln.
def writeln(self, string):
self.f.write(string + '\n')
Itself inside a custom opener. See answers and feedback for this question : subclassing file objects (to extend open and close operations) in python 3
(Context Manager)
I faced this when using ftplib to "retrieve lines" from a file that was "record based" (FB80):
with open('somefile.rpt', 'w') as fp:
ftp.retrlines('RETR USER.REPORT', fp.write)
and ended up with one long record with no newlines, this is likely a problem with ftplib, but obscure.
So this became:
with OpenX('somefile.rpt') as fp:
ftp.retrlines('RETR USER.REPORT', fp.writeln)
It does the job. This is a use case a few people will be looking for.
Complete declaration (only the last two lines are mine):
class OpenX:
def __init__(self, filename):
self.f = open(filename, 'w')
def __enter__(self):
return self.f
def __exit__(self, exc_type, exc_value, traceback):
self.f.close()
def writeln(self, string):
self.f.write(string + '\n')
in order to suspport multiple operating systems use:
file.write(f'some strings and/or {variable}. {os.linesep}')
Actually, when you use the multiline syntax, like so:
f.write("""
line1
line2
line2""")
You don't need to add \n!
Usually you would use \n but for whatever reason in Visual Studio Code 2019 Individual it won't work. But you can use this:
# Workaround to \n not working
print("lorem ipsum", file=f) # Python 3.0 onwards only
print >>f, "Text" # Python 2.0 and under

Categories

Resources