Eryk Sun added the comment:

If you own the only reference you can also delete the reference, which 
deallocates the iterator and closes the handle.

Can you provide concrete examples where os.remove and os.chmod fail? At least 
in Windows 7 and 10 the directory handle is opened with the normal read and 
write sharing, but also with delete sharing. This sharing mode is fairly close 
to POSIX behavior (an important distinction is noted below). I get the 
following results in Windows 10:

    >>> import os, stat
    >>> os.mkdir('test')
    >>> f = open('test/file1', 'w'); f.close()
    >>> f = open('test/file2', 'w'); f.close()
    >>> it = os.scandir('test')
    >>> next(it)
    <DirEntry 'file1'>

rename, chmod, and rmdir operations succeed:

    >>> os.rename('test', 'spam')
    >>> os.chmod('spam', stat.S_IREAD)
    >>> os.chmod('spam', stat.S_IWRITE)
    >>> os.remove('spam/file1')
    >>> os.remove('spam/file2')
    >>> os.rmdir('spam')

Apparently cached entries can be an issue, but this caching is up to WinAPI 
FindNextFile and the system call NtQueryDirectoryFile:

    >>> next(it)
    <DirEntry 'file2'>

An important distinction is that a deleted file in Windows doesn't actually get 
unlinked until all handles and kernel pointer references are closed. Also, once 
the delete disposition is set, no *new* handles can be created for the existing 
file or directory (all access is denied), and a new file or directory with same 
name cannot be created.

    >>> os.listdir('spam')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    PermissionError: [WinError 5] Access is denied: 'spam'

    >>> f = open('spam', 'w')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    PermissionError: [Errno 13] Permission denied: 'spam'

If we had another handle we could use that to rename "spam" to get it out of 
the way, at least. Without that, AFAIK, all we can do is deallocate the 
iterator or wait for it to be exhausted, which closes the handle and thus 
allows Windows to finally unlink "spam":

    >>> next(it)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration

Creating a new file named "spam" is allowed now:

    >>> f = open('spam', 'w')
    >>> f.close()

----------
nosy: +eryksun

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue26111>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to