【问题标题】:Python ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748)Python ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败 (_ssl.c:748)
【发布时间】:2018-03-15 13:38:57
【问题描述】:

我在Python 3.6 应用程序中使用[geopy][1],我必须在使用Windows 2012 Server 的过时机器上运行它。当从应用程序在此服务器上调用此库时会出现问题,因为它返回以下错误:

File "C:\ServAPI\Util.py", line 12, in getLocation
location = geolocator.geocode(name)
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\site-packages\geopy\geocoders\osm.py", line 193, in geocode
self._call_geocoder(url, timeout=timeout), exactly_one
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\site-packages\geopy\geocoders\base.py", line 171, in _call_geocoder
raise GeocoderServiceError(message)
geopy.exc.GeocoderServiceError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:748)

我该如何解决这个问题?我在Windows 2012 Server 上运行Python 3.6.0

更新

代码如下:

from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut
def getLocation(name):
    geolocator = Nominatim()
    try:
        location = geolocator.geocode(name, timeout=5)
        return location
    except GeocoderTimedOut as e:
        print("Error: geocode failed on input %s with message %s" % (e.msg))

【问题讨论】:

    标签: python windows python-3.x ssl geolocation


    【解决方案1】:

    我遇到了同样的问题,但最终也不得不安装 SSL 和 Certifi。我不确定其他人是否会遇到这个问题,但如果有,我就是这样解决的。

    首先安装 Certifi 和 SSL 包,然后

    import certifi
    import ssl
    import geopy.geocoders
    from geopy.geocoders import Nominatim
    ctx = ssl.create_default_context(cafile=certifi.where())
    geopy.geocoders.options.default_ssl_context = ctx
    
    geolocator = Nominatim(scheme='http')
    location = geolocator.reverse("48.8588443, 2.2943506")
    
    print(location.address)
    print (location.raw)
    

    那么,结果是:

    Tour Eiffel, 5, Avenue Anatole France, Gros-Caillou, 7e, Paris, Île-de-France, France métropolitaine, 75007, France
    {'place_id': '62005962', 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright', 'osm_type': 'way', 'osm_id': '5013364', 'lat': '48.8582602', 'lon': '2.29449905431968', 'display_name': 'Tour Eiffel, 5, Avenue Anatole France, Gros-Caillou, 7e, Paris, Île-de-France, France métropolitaine, 75007, France', 'address': {'attraction': 'Tour Eiffel', 'house_number': '5', 'pedestrian': 'Avenue Anatole France', 'suburb': 'Gros-Caillou', 'city_district': '7e', 'city': 'Paris', 'county': 'Paris', 'state': 'Île-de-France', 'country': 'France', 'postcode': '75007', 'country_code': 'fr'}, 'boundingbox': ['48.8574753', '48.8590465', '2.2933084', '2.2956897']}
    

    【讨论】:

      【解决方案2】:

      对于最近遇到这个问题的人,这是我在 2021 年的测试结果: 在我的环境中,python 3.6.8 + geopy 2.2.0 + centos 7 有效; python 2.7.18 + geopy 1.23.0 + centos 8 也可以;但是python 2.7.5 + geopy 1.23.0 + centos 7 不行,报证书错误。

      最后,我找到了根本原因,这是由于 LetsEncrypt 使用的旧“DST”根证书于 9 月 30 日到期;见https://letsencrypt.org/docs/dst-root-ca-x3-expiration-september-2021 .如果使用低于 1.1.0 的 OpenSSL,Python 会受到影响;见https://openssl.org/blog/blog/2021/09/13/LetsEncryptRootCertExpire

      我让 python 2.7.5 + geopy 1.23.0 + centos 7 + openssl 1.0.2k-fips 与解决方法 1 一起工作,即从系统证书中删除 (DST Root CA X3) 根证书,详细步骤是:

      1. 检查 DST Root 是否在 /etc/pki/tls/certs/ca-bundle.crt 中,并且 ISRG Root X1 也在其中。
      2. 将“#DST Root CA X3”部分作为pem文件复制到/etc/pki/ca-trust/source/blacklist目录中
      3. 运行update-ca-trust
      4. 检查 DST Root 不再在 /etc/pki/tls/certs/ca-bundle.crt 中,并且 ISRG Root X1 在 ISRG Root X1 中。

      参考:

      更新:正如@rsc 所指出的,更新您的 ca 证书也可能有效:

      yum upgrade ca-certificates

      【讨论】:

      • 更新到 ca-certificates-2021.2.50-72.el7_9 后,让我们加密链在 RHEL/CentOS 7 上正常工作。应用更新时无需手动编辑/etc/pki/tls/certs/ca-bundle.crt
      【解决方案3】:

      终于有办法了:

      win2012 可能已经过时了 SSL 库。因此,解决方案是明确指出schemahttp

      正确的代码是:

      from geopy.geocoders import Nominatim
      from geopy.exc import GeocoderTimedOut
      
      def getLocation(name):
          geolocator = Nominatim(scheme='http')
          try:
              location = geolocator.geocode(name, timeout=5)
              return location
          except GeocoderTimedOut as e:
              print("Error: geocode failed on input %s with message %s" % (e.msg))
      

      【讨论】:

      • 这个答案在 2021 年不起作用,Brad Ahrens 的 Windows 10 答案对我有用。
      • 当然,我在 4 年前做过这个问题。请更新问题并为您的环境添加解决方案!
      【解决方案4】:

      这对我有用

      import certifi
      import ssl
      import geopy.geocoders
      from geopy.geocoders import Nominatim
      ctx = ssl.create_default_context(cafile=certifi.where())
      geopy.geocoders.options.default_ssl_context = ctx
      nom = Nominatim(scheme = 'http')
      nom.geocode('Empire State , Manhattan , NY')
      

      【讨论】:

        【解决方案5】:

        你好,这个对我有用,因为我在 geopy.geocoders Nomimatim 上遇到错误。

        from geopy.geocoders import ArcGIS
        from geopy.exc import GeocoderTimedOut
        
        def getLocation(name):
            geolocator = ArcGIS(scheme='http')
            try:
                location = geolocator.geocode(name, timeout=5)
                return location
            except GeocoderTimedOut as e:
                print("Error: geocode failed on input %s with message %s" % (e.msg))
        

        【讨论】:

          【解决方案6】:

          我有同样的问题并通过将 create_default_context 更改为 _create_unverified_context 来解决它,并且它起作用了。

          import certifi
          import ssl
          import geopy.geocoders
          
          from geopy.geocoders import Nominatim
          
          ctx = ssl._create_unverified_context(cafile=certifi.where())
          geopy.geocoders.options.default_ssl_context = ctx
          
          locator = Nominatim(scheme='https', user_agent="Test")
          location = locator.reverse("36.3215876,60.5253593")
          
          print(location.raw)
          

          【讨论】:

            猜你喜欢
            • 2018-07-29
            • 2017-06-01
            • 2023-03-03
            • 1970-01-01
            • 2020-01-14
            • 2017-06-25
            • 2019-03-12
            • 1970-01-01
            • 2015-12-21
            相关资源
            最近更新 更多