how to get os.py to use an ./ntpath.py instead of Lib/ntpath.py
ruck
john.ruckstuhl at gmail.com
Mon Sep 10 18:22:05 EDT 2012
On Monday, September 10, 2012 1:16:13 PM UTC-7, Steven D'Aprano wrote:
> On Mon, 10 Sep 2012 10:25:29 -0700, ruck wrote:
>
>
>
> > In Python 2.7.2 on Windows 7,
>
> >
>
> > os.walk() uses isdir(),
>
> > which comes from os.path,
>
> > which really comes from ntpath.py,
>
> > which really comes from genericpath.py
>
> >
>
> > I want os.walk() to use a modified isdir() on my Windows 7. Not knowing
>
> > any better, it seems to me like ntpath.py would be a good place to
>
> > intercept.
>
> >
>
> > When os.py does "import ntpath as path", how can I get python to process
>
> > my customized ntpath.py instead of Lib/ntpath.py ?
>
>
>
> import os
>
> os.path.isdir = my_isdir
>
>
>
> ought to do it.
>
>
>
> This general technique is called "monkey-patching". The Ruby community is
>
> addicted to it. Everybody else -- and a goodly number of the more
>
> sensible Ruby crowd -- consider it a risky, dirty hack that 99 times out
>
> of 100 will lead to blindness, moral degeneracy and subtle, hard-to-fix
>
> bugs.
>
>
>
> They are right to be suspicious of it. As a general rule, monkey-patching
>
> is not for production code. You have been warned.
>
>
>
> http://www.codinghorror.com/blog/2008/07/monkeypatching-for-humans.html
>
>
>
>
>
> [...]
>
> > Why? Because the genericpath implementation relies on os.stat() which
>
> > uses Windows API function that presumes or enforces some naming
>
> > conventions like "doesn't end with a space or a period". But the NTFS
>
> > actually supports such filenames and dirnames, and some sw (like cygwin)
>
> > lets users make files & dirs without restricting. So, cygwin users like
>
> > me may have file 'voo...\\doo' which os.walk() cannot ordinarily walk.
>
> > That is, the isdir('voo...') returns false because the underlying
>
> > os.stat is assessing 'voo' instead of 'voo...' .
>
>
>
> Please consider submitting a patch that adds support for cygwin paths to
>
> the standard library. You'll need to target 3.4 though, 2.7 is now a
>
> maintenance release with no new features allowed.
>
>
>
>
>
> > The workaround is to
>
> > pass os.stat a fullpathname that is prefixed with r'\\?\' so the Windows
>
> > API recognizes that you do NOT want the name filtered.
>
> >
>
> > Better said by Microsoft:
>
> > "For file I/O, the "\\?\" prefix to a path string tells the Windows APIs
>
> > to disable all string parsing and to send the string that follows it
>
> > straight to the file system.
>
>
>
> That's not so much a workaround as the officially supported API for
>
> dealing with the situation you are in. Why don't you just prepend a '?'
>
> to paths like they tell you to?
>
>
>
>
>
> --
>
> Steven
Steven says:
That's not so much a workaround as the officially supported API for
dealing with the situation you are in. Why don't you just prepend a '?'
to paths like they tell you to?
Good idea, but the first thing os.walk() does is a listdir(), and os.listdir() does not like the r'\\?\' prefix. In other words,
os.walk(r'\\?\C:Users\john\Desktop\sandbox\goo')
does not work.
Also, your recipe worked for me --
I'm walking 'goo' which contains 'voo.../doo'
import os
import genericpath
def my_isdir(s):
return genericpath.isdir('\\\\?\\' + os.path.abspath(s + '\\'))
print 'os.walk(\'goo\') with standard isdir()'
for root, dirs, files in os.walk('goo'):
print root, dirs, files
print 'os.walk(\'goo\') with modified isdir()'
os.path.isdir = my_isdir
for root, dirs, files in os.walk('goo'):
print root, dirs, files
yields
os.walk('goo') with standard isdir()
goo [] ['voo...']
os.walk('goo') with modified isdir()
goo ['voo...'] []
goo\voo... [] ['doo']
About monkeypatching, generally -- thanks for the pointer to that discussion. That sounded like a lot of wisdom and lessons learned being shared.
About me suggesting a patch -- I'll sleep on that :)
Thanks Steven!
John
More information about the Python-list
mailing list