简体   繁体   中英

Python 2.6: os.rename() or os.renames() reports OSError but filename is None

If you call os.rename providing files or directories that do not exist, the OSError that is raised omits the filename by setting it to None . Is this a bug in 2.6 that has been fixed in some later version?

You can reproduce the issue by simply doing:

python -c 'import os ; os.rename("/tmp/abc", "/tmp/cba")'

Where neither /tmp/abc nor /tmp/cba exist.

I am just wondering if I should implement a wrapper to os.rename to intercept OSError and correct the filename attribute before resending the error.

Update

I implemented a simple test wrapper, which produces the desired behaviour:

$ /tmp/osrename.py
Traceback (most recent call last):
File "/tmp/osrename.py", line 26, in <module>
  os.rename('/tmp/abc', '/tmp/cba')
File "/tmp/osrename.py", line 8, in __os_rename
  os_rename(a, b)
OSError: [Errno 2] No such file or directory: '/tmp/abc'

Here is the implementation:

import os, sys

def __os_rename_wrapper(os_rename):
    def __os_rename(a, b):
        try:
            os_rename(a, b)

        except OSError:
            exc = sys.exc_info()[1]

            if getattr(exc, 'filename', None) is None:
                exc.filename = "{0} -> {1}".format(repr(a), repr(b))

            raise

    __os_rename.__name__ = os_rename.__name__
    __os_rename.__doc__ = os_rename.__doc__

    return __os_rename

os.rename = __os_rename_wrapper(os.rename)


os.rename('/tmp/abc', '/tmp/cba')

Is there a way to hook module loading so that these sort of fixes can be applied dynamically?

The same happens in python 2.7.8 so I guess that it was intentional.

BUT:

In python 3.4 a second attribute filename2 was added to OSError as stated by @Random832 and the attributes are set correctly.

This PEP 3151 may shed a bit of light, in particular:

Since WindowsError is coalesced into OSError, the latter gains a winerror attribute under Windows. It is set to None under situations where it is not meaningful, as is already the case with the errno , filename and strerror attributes (for example when OSError is raised directly by Python code).

and below:

In order to preserve useful compatibility , these subclasses should still set adequate values for the various exception attributes defined on the superclass (for example errno , filename , and optionally winerror ).

The PEP is marked as accepted for version 3.3. Moreover 3.3 docs says:

For exceptions that involve a file system path (such as open() or os.unlink()), the exception instance will contain an additional attribute, filename, which is the file name passed to the function.

It isn't exactly clear for which functions the attribute is set but based on the above I would say that the rename function definitely involves a file name, and therefore the filename attribute should be set.

If you find any other PEP regarding this, feel free to add it.

The only reason I can think of at the moment is that in the rename function you use two file names, so it might be unclear which one to set on the exception filename attribute (any thoughts about this?).

Your solution regarding the correction of the attribute is doable if you need the value to be set, at least in my opinion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM