Setting the sys.stdout to a text file

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
Iyassou
Posts: 42
Joined: Sun Jun 26, 2016 9:15 am

Setting the sys.stdout to a text file

Post by Iyassou » Sat Jul 02, 2016 7:42 am

Hello,

the title is pretty straightforward, what I want to do is print matrices in a table format onto a text file. So far I've been printing them in a table format onto the REPL but now I want to have the Pyboard print the matrices onto a text file for logging/storing purposes. I imported the sys module and wrote:

Code: Select all

sys.stdout = open("output.txt", "w")
that way every time I would use a print() statement the string in between the parentheses would be printed onto my output.txt file. However, I received this error:

Code: Select all

AttributeError: 'module' object has no attribute 'stdout'
The Pyboard's MicroPython documentation (here's the link: https://docs.micropython.org/en/latest/ ... sys.stdout) says that sys does have a stdout attribute.

Did I misunderstand the error or did I make a mistake in my code?

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: Setting the sys.stdout to a text file

Post by deshipu » Sat Jul 02, 2016 7:57 am

You can't monkey-patch modules implemented in C that way. Just modify your code to write to the file properly.

Iyassou
Posts: 42
Joined: Sun Jun 26, 2016 9:15 am

Re: Setting the sys.stdout to a text file

Post by Iyassou » Sat Jul 02, 2016 9:27 am

Ok. I wrote:

Code: Select all

output = open("output.txt", "w")
and replaced every print() statement with

Code: Select all

output.write()
My program runs into OSError 22 at line 156 where I wrote:

Code: Select all

output.write("\n")

I tried specifying that the newline is '\n' by writing:

Code: Select all

output = open("output.txt", "w", newline = '\n')
but I got this error:

Code: Select all

TypeError: extra keyword arguments given
What should I do?

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: Setting the sys.stdout to a text file

Post by deshipu » Sat Jul 02, 2016 10:09 am

Works for me. Can you create files in the filesystem at all? Does your esp8266 module have more than 500kB of flash?
output = open("output.txt", "w", newline = '\n')
I don't think the "newline" parameter is supported.

Iyassou
Posts: 42
Joined: Sun Jun 26, 2016 9:15 am

Re: Setting the sys.stdout to a text file

Post by Iyassou » Sat Jul 02, 2016 10:48 am

My Pyboard has 48kb of flash which is why I'm using a 1GB SD card. Do I have to specify the output.txt file's location as being "/sd/output.txt"?

When I got my Pyboard I wrote a small program that turned the LEDs on and off. Later when I needed to expand my storage, I backed up all of the files on my Pyboard to my PC, made my Pyboard files the same as they were when I first opened them, unplugged my Pyboard, inserted an SD card into my Pyboard and plugged it back into my PC. The SD card was immediately recognized as my Pyboard's storage, I copied my backed up files there and I've been running programs from there ever since.

User avatar
deshipu
Posts: 1388
Joined: Thu May 28, 2015 5:54 pm

Re: Setting the sys.stdout to a text file

Post by deshipu » Sat Jul 02, 2016 3:17 pm

Iyassou wrote:My Pyboard has 48kb of flash which is why I'm using a 1GB SD card. Do I have to specify the output.txt file's location as being "/sd/output.txt"?
Ah, sorry, I confused the sections of the forum again, and assumed you have an esp8266. Really sorry, please ignore my responses.

Iyassou
Posts: 42
Joined: Sun Jun 26, 2016 9:15 am

Re: Setting the sys.stdout to a text file

Post by Iyassou » Sat Jul 02, 2016 8:29 pm

No worries. I figured it out at the end. I'm sorry but I forgot to mention that the code was inside a file other than my main.py file, a sort of initialization file if you will. As a first fix-around I decided to open the file in both my main.py and initialization.py files, but that didn't work.
Then in my initialization.py file I wrote:

Code: Select all

output = open("output.txt", "w")
at the very beginning that way it would be considered a global variable and I would be able to use it inside any of my post-defined functions. Problem is I wanted to use it inside of class methods that I would define in initialization.py but that I would be calling from my main.py file. The first fix I tried was opening, writing and closing the output.txt file inside of the different class methods of initialization.py. That didn't work so I changed to class methods to make them return a string and in my main.py file I would write:

Code: Select all

output = open("output.txt", "w")  # At the beginning of the program

output.write(class_instance.method())  # Whenever I would need to 'write' the results of calling a class method

output.close()  # At the end of the program

Thank you for your help anyway deshipu!

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Setting the sys.stdout to a text file

Post by pythoncoder » Sun Jul 03, 2016 6:23 am

In general it's not good practice to leave a write file open for the duration of a program. This is because if the program fails or is interrupted the file is left open. Data may still be buffered in RAM and there is a risk of data loss and file corruption. The best way to write to files is to use a Python context manager to open the file each time you want to write data out. The context manager ensures the file is closed properly even if an exception occurs:

Code: Select all

myfile = '/sd/output.txt'
# Perhaps at various points in your program:
with open(myfile, 'w') as output: # Each time you want to write to the file
	output.write(class_instance.method())
	output.write(class_instance.another_method()) # maybe something else needs writing
# Now the file is closed and the data will be correct.
Peter Hinch
Index to my micropython libraries.

Post Reply