Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Backspace" over last character written to file

Tags:

python

I have a Python application which outputs an SQL file:

sql_string = "('" + name + "', " + age + "'),"
output_files['sql'].write(os.linesep + sql_string)
output_files['sql'].flush()

This is not done in a for loop, it is written as data becomes available. Is there any way to 'backspace' over the last comma character when the application is done running, and to replace it with a semicolon? I'm sure that I could invent some workaround by outputting the comma before the newline, and using a global Bool to determine if any particular 'write' is the first write. However, I think that the application would be much cleaner if I could just 'backspace' over it. Of course, being Python maybe there is such an easier way!

Note that having each insert value line in a list and then imploding the list is not a viable solution in this use case.

like image 912
dotancohen Avatar asked Jun 10 '13 11:06

dotancohen


Video Answer


2 Answers

Use seek to move your cursor one byte (character) backwards, then write the new character:

f.seek(-1, os.SEEK_CUR)
f.write(";")

This is the easiest change, maintaining your current code ("working code" beats "ideal code") but it would be better to avoid the situation.

like image 165
nOw2 Avatar answered Sep 28 '22 06:09

nOw2


How about adding the commas before adding the new line?

first_line = True

...

sql_string = "('" + name + "', " + age + "')"

if not first_line:
    output_files['sql'].write(",")
first_line = False

output_files['sql'].write(os.linesep + sql_string)
output_files['sql'].flush()

...

output_files['sql'].write(";")
output_files['sql'].flush()

You did mention this in your question - I think this is a much clearer to a maintainer than seeking commas and overwriting them.

EDIT: Since the above solution would require a global boolean in your code (which is not desirable) you could instead wrap the file writing behaviour into a helper class:

class SqlFileWriter:

    first_line = True

    def __init__(self, file_name):
        self.f = open(file_name)

    def write(self, sql_string):
        if not self.first_line:
            self.f.write(",")
        self.first_line = False

        self.f.write(os.linesep + sql_string)
        self.f.flush()

    def close(self):
        self.f.write(";")
        self.f.close()


output_files['sql'] = SqlFileWriter("myfile.sql")
output_files['sql'].write("('" + name + "', '" + age + "')")

This encapsulates all the SQL notation logic into a single class, keeping the code readable and at the same time simplifying the caller code.

like image 25
seanhodges Avatar answered Sep 28 '22 07:09

seanhodges