عطلان مختلفان يطبعان نفس تتبّع pip، والإصلاح المناسب لأحدهما يجعل الآخر أسوأ. العميل الأقدم من أن يذكر مضيفًا منفّقًا يحتاج إلى ترقية. الوسيط الذي يعيد توقيع الحركة يحتاج إلى شهادة جذر موثوقة، لا إلى تخفيض الإصدار. حدّد أي العطلين لديك قبل أن تعدّل متغيّر وسيط، لأن المسارين يقودان في اتجاهين متعاكسين.

اقرأ الإطارات الأخيرة قبل لمس الإعدادات

موضع انتهاء التتبّع يخبرك أي طبقة استسلمت. إذا كانت الإطارات الختامية داخل شيفرة TLS المضمّنة في urllib3 لدى pip والنص يشتكي من اسم مضيف، فمكتبة العميل لم تُكمل خطوة تحقّق، وهذا عطل إصدار أكثر بكثير من كونه عطل شهادة. وإذا كان النص يبلّغ بدل ذلك عن اتصال مرفوض أو اسم وسيط غير محلول أو خطأ HTTP 407، فالطرف الآخر من النفق هو المسؤول ولا ترقية ستغيّره.

التقط إصدار pip ومتغيّرات الوسيط في الصدفة نفسها التي تفشل. الصدفة التي فُتحت قبل ظهور النفق تحمل قيمًا مختلفة عن تلك التي فُتحت بعده، والفرق بينهما هو غالبًا التشخيص كله.

python3 -m pip --version
env | grep -i -E 'proxy|no_proxy'

عندما يكون العميل أقدم من النفق

إصدارات pip الأقدم كانت تضمّ مكدّس HTTPS يفقد اسم المضيف الهدف بمجرد أن يلتفّ النفق حول المقبس. رسالة check_hostname هي ما يصدره ذلك المكدّس عندما يبلغ التحقّق دون اسم يقارن به. الترقية تزيل العطل لأن العميل الأحدث يحفظ الاسم عبر المصافحة، والتغيير رخيص بما يكفي لتجربته أولًا كلما أشارت الإطارات الختامية إلى شيفرة TLS مضمّنة.

إذا تعذّر الوصول إلى الفهرس من الجهاز الذي يفشل، فاجلب ملف wheel حاليًا على مضيف يستطيع ذلك وثبّته من الملف. استخدم اسم الملف الذي نزّلته فعليًا بدل إصدار منسوخ من تدوينة.

python3 -m pip install --upgrade pip
python3 -m pip install ./pip-24.2-py3-none-any.whl

عندما يعيد الوسيط توقيع الحركة

الوسيط الذي ينهي TLS ويعيد إصدار الشهادات تحت جذر مؤسسي ينتج خطأً مختلفًا: certificate verify failed، لا شكوى اسم مضيف. هذا الفرق هو الدليل، لأن العميل وصل إلى خادم ثم رفض الهوية التي عُرضت عليه. الإصلاح هو الوثوق بذلك الجذر صراحةً، إما لأمر واحد أو عبر متغيّر PIP_CERT، حتى يتمكّن العميل من بناء سلسلة إلى ما يقدّمه الوسيط. وإضافة الجذر إلى مخزن ثقة النظام تعمل أيضًا، لكنها تغيّر الثقة لكل برنامج على الجهاز، وهذا قرار أكبر من إصلاح تثبيت حزمة واحدة.

أبقِ --trusted-host أداة تشخيص، لا حالة استقرار. فهو يوقف الفحص الذي كنت تحاول الحفاظ عليه، فتبدو الشهادة الخاطئة فعلًا سليمة بعده. إذا استخدمته لتثبيت حزمة واحدة، فأزله وأصلح السلسلة قبل الإصدار التالي.

شيفرة Python الخاصة بك تتجاهل إعدادات pip كليًا. نداء requests يحتاج إلى تمرير الوسيط والحزمة حيث تراهما تلك الجلسة، ولهذا يضبط المقطع أدناه كليهما على كائن الجلسة.

pip install --cert /usr/local/share/ca-certificates/corp-root.crt requests
export PIP_CERT=/usr/local/share/ca-certificates/corp-root.crt
s = requests.Session()
s.proxies = {"https": "http://10.20.30.40:8080"}
s.verify = "/usr/local/share/ca-certificates/corp-root.crt"
s.get("https://pypi.org/simple/", timeout=15)

عندما يكون الطرف الآخر أو المنفذ خاطئًا

كثيرًا ما يعيد عميل النفق كتابة وسيط النظام أثناء اتصاله، ما قد يترك pip موجّهًا إلى مضيف لا يجيب أبدًا على ذلك المنفذ. اختبر الطرف الآخر بعميل ليس pip قبل أن تغيّر أي إعداد في pip. إذا فشل curl بالوسيط نفسه، فالعطل فوق pip ولن تساعد أي كمية من الإعداد داخل pip.

علم الأمر ومتغيّرات البيئة يقولان الشيء نفسه لنطاقين مختلفين: العلم ينطبق على استدعاء واحد، والمتغيّرات على كل عملية تبدأ بعده. أضف NO_PROXY لفهرس داخلي حتى تتجاوز حركة الحزم الخاصة الطريق الدوري عبر النفق.

curl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/
pip install --proxy http://proxy.corp.internal:8080 requests

احفظ الإعداد وأثبت أن المسار يعمل

خزّن الوسيط في إعدادات pip نفسها عندما يجب أن يبقى بعد الصدفة الحالية، ثم اقرأ ما سيستخدمه pip فعلًا. مخرجات debug تسمّي الملف والمتغيّر خلف كل قيمة، وهذا يحسم الجدل حول الأولوية أسرع من قراءة التوثيق.

التحقّق يستخدم عميلين عن قصد. طلب المكتبة القياسية يثبت المسار وسلسلة الثقة، بينما التنزيل يثبت أن إعدادات pip نفسها تتفق معهما. عندما ينجح الأول ويفشل الثاني، فالفرق داخل pip لا في الشبكة.

pip config set global.proxy http://proxy.corp.internal:8080
pip config debug
python3 -c "import urllib.request as r; print(r.urlopen('https://pypi.org/simple/').status)"
pip download --no-deps -d /tmp/wheelcheck requests
What you seeFirst commandRepair
hostname message inside vendored TLS framespython3 -m pip --versionupgrade the client
certificate verify failed after the tunnelcurl -x http://proxy.corp.internal:8080 --head https://pypi.org/simple/trust the corporate root
connection refused or HTTP 407env | grep -i -E 'proxy|no_proxy'correct host, port or credentials

مقالات ذات صلة