[Python-Dev] Importing DLLs on Windows

M.-A. Lemburg mal@lemburg.com
Sat, 21 Apr 2001 12:35:00 +0200


Tim Peters wrote:
> 
> Sorry for the delay -- I had a hard time understanding what this writeup
> meant, so had to download the package and try it.

Oh, sorry that I wasn't clear enough. Referring to the mxNumber
package, I am seeing this situation:

# This works... (note the start directory)

C:\WINDOWS>python
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> import mx.Number
>>> print mx.Number.Float(3.141)
3.14100000000000001421e+0
>>>

# This doesn't.... (from the Python install directory)

D:\Python21>python
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> import mx.Number
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "d:\python21\mx\Number\__init__.py", line 9, in ?
    from Number import *
  File "d:\python21\mx\Number\Number.py", line 11, in ?
    from mxNumber import *
  File "d:\python21\mx\Number\mxNumber\__init__.py", line 21, in ?
    from mxNumber import *
ImportError: DLL load failed: Ein der fnr die Ausfnhrung dieser Anwendung notwen
dige Bibliothekdateien kann nicht gefunden werden.
>>>

# OTOH, this works.... (one level below the Python install directory)

D:\Python21>cd mx

D:\Python21\mx>python
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> import mx.Number
>>>
 
> [M.-A. Lemburg]
> > Python or Windows seems to have trouble importing DLLs when
> > inside packages. I'm working on an extension which pulls in a
> > DLL gmp31.dll which lives inside a package dir mx/Number/mxNumber
> > along side the Python wrapper extension mxNumber.pyd.
> 
> Concretely, I have these files now, under my Python 2.1 installation
> directory:
> 
> C:\Python21>dir/b/on mx\Number\mxNumber
> gmp31.dll
> mxNumber.pyd
> mxNumber.h
> test.py
> __init__.py
> 
> C:\Python21>
> 
> > Currently, I'm using this code in the subpackage's __init__.py:
> 
> And by "the subpackage" here I believe you mean the tail-end mxNumber
> directory, previously called "a package".  IOW, you're talking specifically
> about
> 
>     \Python21\mx\Number\mxNumber\__init__.py

Right.
 
> If you meant something else, scream.
>
> > # On Windows we also distribute the GMP DLL (in the win32 subdir). To
> > # have Win32 find the DLL we need to be explicit about the path in
> > # sys.path though. This trick works for all startup directories
> > # *except* \PythonXX (for some reason this fails), but is not thread
> > # safe...
> > import sys, os
> > if sys.platform[:3] == 'win':
> >     abspath = os.path.abspath(__path__[0])
> >     sys.path.insert(0, abspath)
> >     from mxNumber import *
> >     sys.path.remove(abspath)
> >
> > else:
> >     from mxNumber import *
> 
> > I don't have any clue why the import works
> 
> Which import are you talking about?  Please show exactly what you do that
> fails -- I haven't been able to find any problem here.  For example, I
> replaced
> 
>     \Python21\mx\Number\mxNumber\__init__.py
> 
> which contains the code you showed above, with this two-liner:
> 
> from mxNumber import *
> from mxNumber import __version__
> 
> Having done that, here's a shell session started in the installation
> directory, and after a reboot "just to make sure":
> 
> C:\Python21>python
> Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
> Type "copyright", "credits" or "license" for more information.
> >>> from mx.Number import *
> >>> Integer(928349238479328749L)**2
> 861832308585149602001042573617905001
> >>>
> 
> So nothing failed. 

Hmm, you are right, it does work for me too (I wonder why I
thought it failed without the sys.path tweaking... probably
just tested from the Python install dir):

C:\WINDOWS>python
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> import mx.Number
>>> print mx.Number.Float(3.141)
3.14100000000000001421e+0
>>>
C:\WINDOWS>d:

D:\Python21\mx>python
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> import mx.Number
>>> print mx.Number.Float(3.141)
3.14100000000000001421e+0
>>>
D:\Python21\mx>cd ..

D:\Python21>python
Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
>>> import mx.Number
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "d:\python21\mx\Number\__init__.py", line 9, in ?
    from Number import *
  File "d:\python21\mx\Number\Number.py", line 11, in ?
    from mxNumber import *
  File "d:\python21\mx\Number\mxNumber\__init__.py", line 11, in ?
    from mxNumber import *
ImportError: DLL load failed: Ein der fnr die Ausfnhrung dieser Anwendung notwen
dige Bibliothekdateien kann nicht gefunden werden.
>>>

> What do *you* do that fails?  Here's another session
> started from a "random" directory:
> 
> C:\Code>\python21\python
> Python 2.1 (#15, Apr 16 2001, 18:25:49) [MSC 32 bit (Intel)] on win32
> Type "copyright", "credits" or "license" for more information.
> >>> from mx.Number import *
> >>> Integer(92387498327493243879L)**2
> 8535449847212566935021074270390170966641
> >>>
> 
> Same thing.
> 
> > from everywhere *except* the Python21 install directory...
> 
> It would more helpful to name a specific directory than to make an untrue
> claim <wink -- but you didn't try every directory other than Python21, and
> the specific directories you actually did try may be important>.

Ok, ok ;-)

Please try starting Python from your Python install dir and
then do the import. BTW, I'm doing this on Windows 95 in case
this matters (which I'm sure it does :-/).
 
> BTW, it's a mondo cool package!  I had a lot of fun with it. 

Thanks :)

> But then I was
> able to, since I stopped trying to guess what your problem was <wink>.
> What's up?  I was running Win98SE in the above, but that shouldn't make a
> difference.  Perhaps, during development, you left crap sitting around in
> your installation directory that's confusing your attempts to import things?
> If not, please be very explicit about what you do that fails, and what
> "fails" means (crash, ImportError, Windows error box, ...?).

"fail" means that Python cannot find the gmp31.dll sitting right
next to the mxNumber.pyd in the same directory. This should normally
work, but somehow doesn't when Python is started from the install
dir:

>>> import mx.Number
import mx # directory mx
# trying mx\__init__.pyd
# trying mx\__init__.dll
# trying mx\__init__.py
# mx\__init__.pyc matches mx\__init__.py
import mx # precompiled from mx\__init__.pyc
import mx.Number # directory mx\Number
# trying mx\Number\__init__.pyd
# trying mx\Number\__init__.dll
# trying mx\Number\__init__.py
# mx\Number\__init__.pyc matches mx\Number\__init__.py
import mx.Number # precompiled from mx\Number\__init__.pyc
# trying mx\Number\Number.pyd
# trying mx\Number\Number.dll
# trying mx\Number\Number.py
# mx\Number\Number.pyc matches mx\Number\Number.py
import mx.Number.Number # precompiled from mx\Number\Number.pyc
import mx.Number.mxNumber # directory mx\Number\mxNumber
# trying mx\Number\mxNumber\__init__.pyd
# trying mx\Number\mxNumber\__init__.dll
# trying mx\Number\mxNumber\__init__.py
# mx\Number\mxNumber\__init__.pyc matches mx\Number\mxNumber\__init__.py
import mx.Number.mxNumber # precompiled from mx\Number\mxNumber\__init__.pyc
# trying mx\Number\mxNumber\mxNumber.pyd
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "d:\python21\mx\Number\__init__.py", line 9, in ?
    from Number import *
  File "d:\python21\mx\Number\Number.py", line 11, in ?
    from mxNumber import *
  File "d:\python21\mx\Number\mxNumber\__init__.py", line 11, in ?
    from mxNumber import *
ImportError: DLL load failed: Ein der fnr die Ausfnhrung dieser Anwendung notwen
dige Bibliothekdateien kann nicht gefunden werden.
>>>

>From C:\WINDOWS there's no problem:

import mx # directory d:\python21\mx
# trying d:\python21\mx\__init__.pyd
# trying d:\python21\mx\__init__.dll
# trying d:\python21\mx\__init__.py
# d:\python21\mx\__init__.pyc matches d:\python21\mx\__init__.py
import mx # precompiled from d:\python21\mx\__init__.pyc
import mx.Number # directory d:\python21\mx\Number
# trying d:\python21\mx\Number\__init__.pyd
# trying d:\python21\mx\Number\__init__.dll
# trying d:\python21\mx\Number\__init__.py
# d:\python21\mx\Number\__init__.pyc matches d:\python21\mx\Number\__init__.py
import mx.Number # precompiled from d:\python21\mx\Number\__init__.pyc
# trying d:\python21\mx\Number\Number.pyd
# trying d:\python21\mx\Number\Number.dll
# trying d:\python21\mx\Number\Number.py
# d:\python21\mx\Number\Number.pyc matches d:\python21\mx\Number\Number.py
import mx.Number.Number # precompiled from d:\python21\mx\Number\Number.pyc
import mx.Number.mxNumber # directory d:\python21\mx\Number\mxNumber
# trying d:\python21\mx\Number\mxNumber\__init__.pyd
# trying d:\python21\mx\Number\mxNumber\__init__.dll
# trying d:\python21\mx\Number\mxNumber\__init__.py
# d:\python21\mx\Number\mxNumber\__init__.pyc matches d:\python21\mx\Number\mxNu
mber\__init__.py
import mx.Number.mxNumber # precompiled from d:\python21\mx\Number\mxNumber\__in
it__.pyc
# trying d:\python21\mx\Number\mxNumber\mxNumber.pyd
import mx.Number.mxNumber.mxNumber # dynamically loaded from d:\python21\mx\Numb
er\mxNumber\mxNumber.pyd
>>>

Could this have something to do with absolute search paths (these
work) vs. relative ones (these don't) ?

-- 
Marc-Andre Lemburg
______________________________________________________________________
Company & Consulting:                           http://www.egenix.com/
Python Pages:                           http://www.lemburg.com/python/