0

My goal is to have a task running in the background that sends any changes to a file to my discord server. This is what I've written:

async def readfile():
    global carlson
    await carlson.wait_until_ready()
    server_channel = carlson.get_channel(channel_id_goes_here)
    # above code gets channel id once the bot is fully connected
    while True:
        file = os.open('testfile', os.O_NONBLOCK | os.O_RDWR)
        os.lseek(file, 0, 0)
        fileread = os.read(file, os.path.getsize(file)).decode()
        if fileread != '':
            await server_channel.send(fileread)  # sends changes to the server
            os.write(file, ''.encode())  # seems to append to the file, I want to overwrite what's already there
        os.close(file)
asyncio.get_event_loop().create_task(readfile())  # makes code asynchronous

Here's what happened when I set the empty string im writing to the file to 'a', and manually wrote the text 'hola' to the file:

Visual output

I've even checked the file, and sure enough, the new value is 'holaaaaaaaaaaaa'. I'm unsure how to overwrite the file instead of appending to it. I can't use open() to open the file, as that blocks the rest of the program.

jvadair
  • 35
  • 1
  • 7
  • 3
    The same file pointer is used for reading and writing. With the read you place it at the end. – Michael Butscher Nov 21 '20 at 22:31
  • @MichaelButscher I guess I'm not entirely sure what you mean. If you meant the version of the file before os.write() is the one being written, I modified the code to read and write separately, to the same effect. – jvadair Nov 21 '20 at 22:46
  • 1
    Are you sure you want to write to your file in-place at all? Creating a new, temporary file with a randomly-generated name; writing it from scratch; and then renaming it over the input file is the general best practice. See [How to do atomic file replacement?](https://stackoverflow.com/questions/7645338/how-to-do-atomic-file-replacement) – Charles Duffy Nov 21 '20 at 22:50
  • 1
    ...btw, you _can_ do blocking operations without interrupting your async server, _if you dispatch them to be done by a different thread_. – Charles Duffy Nov 21 '20 at 22:51
  • 1
    Oh, one other thing -- if you want to empty your file so there can't be extra content at the end that didn't get rewritten, use `truncate()` after the `seek(0)`. – Charles Duffy Nov 21 '20 at 22:52
  • 1
    So: (1) Calling `lseek(file, 0, 0)` a second time after the read and before the write will ensure your write happens at the beginning of the file. (2) Calling `truncate()` after that second seek and before the write (or after the write, if you prefer) will ensure there isn't extra content at the end of your file left over from prior use. – Charles Duffy Nov 21 '20 at 22:55
  • @CharlesDuffy Tysm, using those two commands has made it work perfectly. I didn't notice the original commenter said pointer, hence the confusion. os.truncate() is definitely what i needed. – jvadair Nov 21 '20 at 23:01

0 Answers0