When will os.remove fail?

eryk sun eryksun at gmail.com
Tue Mar 14 13:40:04 EDT 2017


On Tue, Mar 14, 2017 at 1:07 PM, Chris Angelico <rosuav at gmail.com> wrote:
> On Tue, Mar 14, 2017 at 10:32 PM, Steve D'Aprano
> <steve+python at pearwood.info> wrote:
>
>> I take it that you *can* delete open files, but only if the process that
>> opens them takes special care to use "delete sharing". Is that correct?
>
> Yes, but you can't always control the process that opens them. For
> example, it's annoyingly difficult to update a running executable.

One option is to move it out of the way. For example:

    src = Path(sys.executable)
    dst = Path('C:/Temp/python.exe')

    >>> src.exists(), dst.exists()
    (True, False)

    >>> src.rename(dst)
    >>> src.exists(), dst.exists()
    (False, True)

    >>> dst.rename(src)
    >>> src.exists(), dst.exists()
    (True, False)

> More generally, a handle is just an opaque cookie that represents a
> thing. If you do cross-platform socket programming, you'll find that
> on Unix, creating a socket returns a "file descriptor"; but on
> Windows, it returns a "socket handle". Aside from the fact that socket
> handles can only be used with socket functions (making them harder to
> pass to other processes etc), the two concepts work broadly the same
> way: you have a small integer value that represents a large resource.

Usually a socket is a handle for a File object, from opening the AFD
(ancillary function) device. You can use it with [Nt]ReadFile and
[Nt]WriteFile [1]. It's just better to use it with Winsock APIs like
WSARecv and WSASend, which make NtDeviceIoControlFile calls.

But there's also the headache of the deprecated layered service
providers, for which a socket isn't really a File object and using
File functions is inefficient.

[1]: https://msdn.microsoft.com/en-us/library/ms740522

Similarly for a console File handle you can use [Nt]ReadFile and
[Nt]WriteFile, which encode and decode byte streams using the console
input and output codepages. But it's generally better to use
ReadConsole and WriteConsole, which allow using the UTF-16 API via
NtDeviceIoControlFile. ReadConsole also allows defining a custom
control mask, if, for example, you want Ctrl+D to signal EOF.

> I'm terrified to think what the interactions would be between this and
> the Ubuntu subsystem in Win 10. What're the semantics of unlinkat()?
> What about the common practice of creating a file and then unlinking
> it so it doesn't show up in the directory? (And is that different on a
> file system that supports hard links?) Or are heaps of POSIX features
> simply not available?

WSL uses the VolFs file system for the Linux VFS. This should
implement native Linux file-system behavior.

The interesting interaction is for Windows drives that are made
available under /mnt. In the following example, in Windows Python I
set the delete disposition on a file named "spam". Then in WSL python3
I checked the directory listing and whether I could stat, remove, or
open the file:

    >>> os.listdir()
    ['spam']

    >>> os.stat('spam')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    FileNotFoundError: [Errno 2] No such file or directory: 'spam'

    >>> os.remove('spam')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    FileNotFoundError: [Errno 2] No such file or directory: 'spam'

    >>> open('spam')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    FileNotFoundError: [Errno 2] No such file or directory: 'spam'

    >>> open('spam', 'w')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    FileNotFoundError: [Errno 2] No such file or directory: 'spam'

Back in Windows I called SetFileInformationByHandle to unset the
delete disposition. Then regular access was restored in WSL:

    >>> s = os.stat('spam')
    >>> s.st_ino, s.st_size
    (35184372088857305, 10)


More information about the Python-list mailing list