ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I don't really see why the file should be closed but python does a lot of automatic closing when the object handle is reassigned or the garbage collection kicks in. I also noticed, that you do not call close() on the files ever which is bad practice and might lead to the files being left open and or data being lost after the node dies. In general I would open and close the files before and after writing to them. This is as simple as:

def write_to_file(self, file_name, data):
    with open(file_name, 'a') as f:
        f.write(data)

The with statement makes sure that the file is closed once it runs out of scope. With the 'a' you set the file to append and will just put new entries in the bottom. This not only accomplishes that you won't get that error any more but also makes sure that all your data is flushed to the file before your node dies.

As a hotfix for your code, you could just add:

if self.stdout_log_callback.closed():
    self.stdout_log_callback.open("put file name here", 'a')
self.stdout_log_callback.write('[callback ' + str(self.callback_bc) + '][ROSPY] I am: %d, I heard %d\n' % (self.about_me_wm.ID, data.id))

But I would advice to use the with solution.

I don't really see why the file should be closed but python does a lot of automatic closing when the object handle is reassigned or the garbage collection kicks in. I also noticed, that you do not call close() on the files ever which is bad practice and might lead to the files being left open and or data being lost after the node dies. In general I would open and close the files before and after writing to them. This is as simple as:

def write_to_file(self, file_name, data):
    with open(file_name, 'a') as f:
        f.write(data)

The with statement makes sure that the file is closed once it runs out of scope. With the 'a' you set the file to append and will just put new entries in the bottom. This not only accomplishes that you won't get that error any more but also makes sure that all your data is flushed to the file before your node dies.

As a hotfix for your code, you could just add:

if self.stdout_log_callback.closed():
    self.stdout_log_callback.open("put file name here", 'a')
self.stdout_log_callback.write('[callback ' + str(self.callback_bc) + '][ROSPY] I am: %d, I heard %d\n' % (self.about_me_wm.ID, data.id))

But I would advice to use the with solution.

EDIT:

Opening and closing the files all the time of course takes longer than just writing. If speed is an issue, you might want to keep the files open all the time. A solution would be to check if the file is open before you try to write and open it if it is not. This might work:

def __init__(self, ...):
    ...
    self.my_file = [open("filename.txt", 'w'), "filename.txt"]
    ...
    rospy.on_shutdown(self.shutdown_hook)

def callback(self, msg):
    self.write_to_file(self.my_file, str(msg))

def write_to_file(self, f, data):
    try:
        f[0].write(data)
    except ValueError:
        f[0] = open(f[1], 'a')
        self.write_to_file(f, data)

def shutdown_hook(self):
    self.my_file.close()

Make sure that all the files are closed in the shutdown_hook which is invoked by ros when your node receives the signal to shutdown via rospy.on_shutdown(self.shutdown_hook). Because if you do not close them, buffered data might be lost because it is not flushed to disk.