ImportError: No module named _md5解決方案

來源:互聯網
上載者:User

將使用cx_freeze打包的python程式copy到別的機器上運行時碰到這樣的錯誤:
jerrykwan@jerrykwan:~/Downloads/exe.linux-x86_64-2.7$ ./server_family_info
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/cx_Freeze/initscripts/Console.py", line 27, in <module>
  File "server_family_info.py", line 14, in <module>
  File "/usr/local/lib/python2.7/site-packages/tornado-2.4.1-py2.7.egg/tornado/web.py", line 59, in <module>
  File "/usr/local/lib/python2.7/email/utils.py", line 27, in <module>
  File "/usr/local/lib/python2.7/random.py", line 49, in <module>
  File "/usr/local/lib/python2.7/hashlib.py", line 136, in <module>
  File "/usr/local/lib/python2.7/hashlib.py", line 71, in __get_builtin_constructor
ImportError: No module named _md5
通過日誌可以看出問題很明顯,應該就是在hashlib模組中出的問題.
hashlib源碼如下:

# This tuple and __get_builtin_constructor() must be modified if a new# always available algorithm is added.__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')algorithms = __always_supported__all__ = __always_supported + ('new', 'algorithms')def __get_builtin_constructor(name):    try:        if name in ('SHA1', 'sha1'):            import _sha            return _sha.new        elif name in ('MD5', 'md5'):            import _md5            return _md5.new        elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):            import _sha256            bs = name[3:]            if bs == '256':                return _sha256.sha256            elif bs == '224':                return _sha256.sha224        elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):            import _sha512            bs = name[3:]            if bs == '512':                return _sha512.sha512            elif bs == '384':                return _sha512.sha384    except ImportError:        pass  # no extension module, this hash is unsupported.    raise ValueError('unsupported hash type %s' % name)def __get_openssl_constructor(name):    try:        f = getattr(_hashlib, 'openssl_' + name)        # Allow the C module to raise ValueError.  The function will be        # defined but the hash not actually available thanks to OpenSSL.        f()        # Use the C function directly (very fast)        return f    except (AttributeError, ValueError):        return __get_builtin_constructor(name)def __py_new(name, string=''):    """new(name, string='') - Return a new hashing object using the named algorithm;    optionally initialized with a string.    """    return __get_builtin_constructor(name)(string)def __hash_new(name, string=''):    """new(name, string='') - Return a new hashing object using the named algorithm;    optionally initialized with a string.    """    try:        return _hashlib.new(name, string)    except ValueError:        # If the _hashlib module (OpenSSL) doesn't support the named        # hash, try using our builtin implementations.        # This allows for SHA224/256 and SHA384/512 support even though        # the OpenSSL library prior to 0.9.8 doesn't provide them.        return __get_builtin_constructor(name)(string)try:    import _hashlib    new = __hash_new    __get_hash = __get_openssl_constructorexcept ImportError:    new = __py_new    __get_hash = __get_builtin_constructorfor __func_name in __always_supported:    # try them all, some may not work due to the OpenSSL    # version not supporting that algorithm.    try:        globals()[__func_name] = __get_hash(__func_name)    except ValueError:        import logging        logging.exception('code for hash %s was not found.', __func_name)# Cleanup locals()del __always_supported, __func_name, __get_hashdel __py_new, __hash_new, __get_openssl_constructor

從hashlib.py的源碼很容易看出,對於hashlib提供的('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')等演算法,hashlib的做法是先去檢驗python內建的_hashlib是否支援openssh,這點兒可以認為是python編譯的時候是否加入了openssl的支援,如果已經擁有openssl的支援,則直接使用python內建的openssl提供的演算法,否則使用其他第三方的演算法
可以確定的是,我們使用cx_freeze進行編譯的時候機器上的python是支援openssl的,但為什麼編譯完的程式卻不具備該功能呢?
通過使用ldd查看動態庫依賴關係可以看出如下資訊:
jerrykwan@jerrykwan:~/Downloads/exe.linux-x86_64-2.7$ ldd server_family_info
    linux-vdso.so.1 =>  (0x00007fff5c5ff000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe755d1f000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe755b1b000)
    libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fe755917000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe75561b000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe75525c000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fe755f53000)
jerrykwan@jerrykwan:~/Downloads/exe.linux-x86_64-2.7$ ldd _hashlib.so
    linux-vdso.so.1 =>  (0x00007fff042f3000)
    libssl.so.6 => not found
    libcrypto.so.6 => not found
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f2ed15fd000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2ed123e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f2ed1a36000)
原來是 libssl.so.6和libcrypto.so.6等動態庫找不到的原因導致hashlib模組認為使用cx_freeze編譯後的python環境不具備openssl支援,進而使用第三方md5等演算法,但此時運行環境中第三方md5等模組也不具備,所以程式運行時出錯
為解決這一問題可以在打包時將libssl.so.6和libcrypto.so.6 copy到運行環境中,也可以調整系統的/etc/ld.so.conf以便很方便的找到libssl.so.6和libcrypto.so.6

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.