Issue 1336582: fileinput device or resource busy error (original) (raw)
Fileinput module can't work with the unicode path names properly.
Here is the reproduction of the error:
---------------8<---------------8<---------------8<---------------8<------- meren@pardus /home/meren $ touch myfile meren@pardus /home/meren $ python
fn = u'/home/meren/myfile' type(fn) <type 'unicode'> import fileinput for line in fileinput.input(fn, inplace = 1): ... print line ... Traceback (most recent call last): File "", line 1, in ? File "/usr/lib/python2.3/fileinput.py", line 231, in next line = self.readline() File "/usr/lib/python2.3/fileinput.py", line 300, in readline os.rename(self._filename, self._backupfilename) OSError: [Errno 16] Device or resource busy
--------------->8--------------->8--------------->8--------------->8-------
This is happening, because the value of the self._filename variable is just the first character of the fn: '/'.
The init method of the FileInput class (/usr/lib/python2.3/fileinput.py) is the responsible one about this malfunction. In the init function it's checking the type of the 'files' variable (in this case it is fn) for an iteration hack:
---------------8<---------------8<---------------8<---------------8<------- (...) def __init__(self, files=None, inplace=0, backup="", bufsize=0): if type(files) == type(''): files = (files,) (...) --------------->8--------------->8--------------->8--------------->8-------
When the type of the 'files' variable is unicode, the value of the 'files' variable is incohorently becoming into this:
files = [u'/', u'h', u'o', u'm', u'e', u'/', u'm', u'e', u'r', u'e' ....
consequently, python is trying to execute os.rename('/', '/.bak') instead of os.rename('/home/meren/myfile', '/home/meren/myfile.bak'). After this function call os module decides to throw an error, normally..
[1], (...) if isinstance(files, basestring): files = (files,) (...)
[2] (...) if type(files) == type(''): files = (files,) (...)
Checking the type of the variable in the init function of the class like [1] is solving the problem (now we are doing it like [2]).. Also, no backward compatibility problem appearing with this replacement.
Here is a small patch to show replacement properly:
---------------8<---------------8<---------------8<---------------8<------- --- fileinput.orig.py 2005-10-24 19:55:53.019413368 +0300 +++ fileinput.py 2005-10-24 19:56:19.590373968 +0300 @@ -184,7 +184,7 @@ """
def __init__(self, files=None, inplace=0,
backup="", bufsize=0):
if type(files) == type(''):
if isinstance(files, basestring): files = (files,) else: if files is None:
--------------->8--------------->8--------------->8--------------->8-------
and here is the result of the same operation after this patch:
---------------8<---------------8<---------------8<---------------8<------- (...) os.rename(self._filename, self._backupfilename) OSError: [Errno 16] Device or resource busy
reload(fileinput) <module 'fileinput' from '/usr/lib/python2.3/fileinput.py'> for line in fileinput.input(fn, inplace = 1): ... print line ...
--------------->8--------------->8--------------->8--------------->8-------
Sorry for the long explanation, Thanks in advice.. Ciao.