I'm using PyQt and I noticed strange behavior when testing my application with Windows (everything is working as expected with Linux).
I have a file that I can read and write and I want to test it from the app:
>>> from PyQt4.QtCore import QFile, QFileInfo
>>> f1 = QFileInfo("C:\Users\Maxime\Desktop\script.py")
>>> f2 = QFile("C:\Users\Maxime\Desktop\script.py")
>>> f1.isWritable()
True
>>> f2.isWritable()
False
So it looks like QFile
is wrong on that test case. But, on another file that is read-only:
>>> f1 = QFileInfo("C:\Program Files (x86)\MySoftware\stuff\script.py")
>>> f2 = QFile("C:\Program Files (x86)\MySoftware\stuff\script.py")
>>> f1.isWritable()
True
>>> f2.isWritable()
False
Now, this is QFileInfo
which is wrong!
So I decided maybe I should use os.access
instead:
>>> import os
>>> os.access("C:\Users\Maxime\Desktop\script.py")
True
>>> os.access("C:\Program Files (x86)\MySoftware\stuff\script.py")
True
So os.access
is also wrong in one case and returns the same results as QFileInfo
.
I have multiple questions:
QFileInfo
and QFile
to test if a file can be written. Should I use one instead of the other?Edit:
A very interesting comment from Frank explained that QFile::isWritable() will always return False since I haven't opened the file.
>>> f = QFile("C:\Users\Maxime\Desktop\script.py")
>>> f.open(QFile.WriteOnly)
True
>>> f.isWritable()
True
>>> f = QFile("C:\Program Files (x86)\MySoftware\stuff\script.py")
>>> f.open(QFile.WriteOnly)
False
>>> f.isWritable()
False
For checking writeability, it shouldn't really matter which one you use.
The main difference with QFileInfo is that, for performance reasons, it caches some of the information about the target file. However, you can use the refresh method to re-read the information, or just use setCaching to switch caching off altogether.
Also, as noted in the question comments, QFile.isWritable will return False if the file has not been opened. This is not a bug. The documentation makes it clear that isWritable checks the OpenMode of the file. This will be zero (QIODevice.NotOpen) before the file is opened, and otherwise defaults to QIODevice.ReadWrite if unspecified.
The only other issue to be aware of is that methods like QFileInfo.isWritable are specific to the current user. Use QFileInfo.permission for ownership information about other classes of user (but note the warning regarding platform differences). This is analogous to the difference between using os.access
and os.stat
.
Finally, here's a simple script that tests writeability:
import os, stat, sip
sip.setapi('QString', 2)
from PyQt4.QtCore import QTemporaryFile, QFile, QFileInfo
tmp = QTemporaryFile()
tmp.setAutoRemove(False)
tmp.open()
tmp.close()
path = tmp.fileName()
info = QFileInfo(path)
print('File: %s' % info.filePath())
print('')
print('Qt Writable: %s' % info.isWritable())
print('Qt Permission: %s' % bool(info.permissions() & QFile.WriteUser))
print('Py Writable: %s' % os.access(path, os.W_OK))
print('Py Permission: %s' % bool(os.stat(path).st_mode & stat.S_IWUSR))
tmp = QFile(path)
tmp.setPermissions(QFile.ReadUser)
print('')
print('Set Permissions: ReadUser')
print('')
info.refresh()
print('Qt Writable: %s' % info.isWritable())
print('Qt Permission: %s' % bool(info.permissions() & QFile.WriteUser))
print('Py Writable: %s' % os.access(path, os.W_OK))
print('Py Permission: %s' % bool(os.stat(path).st_mode & stat.S_IWUSR))
tmp.setPermissions(QFile.WriteUser)
print('')
print('Removed: %s' % tmp.remove())
For me, on both Linux and WinXp, I get results like this:
File: /tmp/qt_temp.TJ1535
Qt Writable: True
Qt Permission: True
Py Writable: True
Py Permission: True
Set Permissions: ReadUser
Qt Writable: False
Qt Permission: False
Py Writable: False
Py Permission: False
Removed: True
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With