Search code examples
pythonpyqtpyqt4temporarytemporary-files

PyQt: QTemporaryFile - unable to read from file


I'm unable to read from temporary file created by QTemporaryFile, maybe you can check the code below...

>>> from PyQt4 import QtCore
>>> fileTemp = QtCore.QTemporaryFile()
>>> fileTemp.open()
True   #file is created
>>> fileTemp.fileName()
PyQt4.QtCore.QString(u'/tmp/qt_temp.TJ2302')
>>> fileTemp.writeData('foobar')
6L     #six bytes are written, great
>>> open(fileTemp.fileName(), 'r').read()
''     #but there is still nothing inside!
>>> fileTemp.size()
6L     #magically, by doing this 'foobar' appears in this tempFile...
       #the same effect gives e.g. fileTemp.readData(1000), but nothing is read
>>> open(fileTemp.fileName(), 'r').read()
'foobar'
>>> fileTemp.readData(1000)
''     #why...
>>> fileTemp.readAll()
PyQt4.QtCore.QByteArray('')
>>> fileTemp.readAll().size()
0      #why...

will be grateful for any help!

EDIT

I've extended QTemporaryFile to behave as expected, but still looking for a more clean solution...

class MyTemporaryFile(QtCore.QTemporaryFile):
    def __init__(self, *argc, **argv):
        QtCore.QTemporaryFile.__init__(self, *argc, **argv)

    def write(self, data):
        f = open(self.fileName(), 'w')
        f.write(data)
        f.close()

    def read(self):
        f = open(self.fileName(), 'r')
        data = f.read()
        f.close()
        return data

Solution

  • If you want to force the OS to write the data to a file you should always flush():

    In [10]: from PyQt4 import QtCore
    
    In [11]: fileTemp = QtCore.QTemporaryFile()
    
    In [12]: fileTemp.open()
    Out[12]: True
    
    In [13]: fileTemp.fileName()
    Out[13]: PyQt4.QtCore.QString(u'/tmp/qt_temp.XM5599')
    
    In [14]: fileTemp.writeData('foobar')
    Out[14]: 6L
    
    In [15]: with open(fileTemp.fileName(), 'r') as f:
       ....:     print(f.read())
       ....:     
    
    
    In [16]: fileTemp.flush()
    Out[16]: True
    
    In [17]: with open(fileTemp.fileName(), 'r') as f:
        print(f.read())
       ....:     
    foobar
    

    Probably the call to size() implicitly forces the OS to flush, hence the behaviour you have observed.