Virtualenv: تجاوز طول Shebang في نقطة قابلة للتنفيذ

تم إنشاؤها على ٢٥ أبريل ٢٠١٤  ·  16تعليقات  ·  مصدر: pypa/virtualenv

عندما يتم إنشاء Virtualenv جديد ، هناك عدد من الأشياء المثبتة في هذا virtualenv. أحد هذه الأشياء هو أداة تثبيت حزمة Python ، pip.

في نظام Linux ، ملف pip القابل للتنفيذ هو برنامج نصي شل. في الجزء العلوي من هذا البرنامج النصي لقذيفة النقطة يوجد سطر shebang (#!) الذي يحدد مترجم python في virtualenv. يحتوي هذا الخط على المسار المطلق لمترجم بايثون.

إذا كان المسار المطلق لمترجم Python في virtualenv طويلًا جدًا (متداخل بعمق و / أو أسماء مسارات كبيرة) ، فقد يتجاوز الحد الأقصى للطول المسموح به لخط shebang.

الحد الأقصى لطول خط shebang محدود في النواة بواسطة BINPRM_BUF_SIZE ، محدد في /usr/include/linux/binfmts.h. على أجهزة Linux التي نظرت إليها ، تم تعيين هذا الحد على 128.

لذلك ، عندما يصبح المسار ، إلى حيث يتم إنشاء python virtualenv ، طويلًا جدًا ، فلن يعمل استخدام نقطة virtualenv هذه. ستفشل بسبب الخطأ: "مترجم سيئ: لا يوجد مثل هذا الملف أو الدليل"

الحل البديل لهذه المشكلة هو عدم تشغيل pip مباشرةً ، ولكن عن طريق تشغيل مترجم python الخاص بـ virtualenv وتمرير نص النقطة إلى python كمصدر لتنفيذه.

التعليق الأكثر فائدة

إذا وجد أي شخص هذا مربكًا:

الحل البديل لهذه المشكلة هو عدم تشغيل pip مباشرةً ، ولكن عن طريق تشغيل مترجم python الخاص بـ virtualenv وتمرير نص النقطة إلى python كمصدر لتنفيذه.

هذا يعني أنه بدلاً من pip install -r requirements.txt افعل python -m pip install -r requirements.txt

ال 16 كومينتر

أواجه هذه المسألة أيضا.

أنا أيضا.

شكرا على الحل!

لاحظ أن البرامج النصية للغلاف يتم إنشاؤها بالفعل بواسطة setuptools (إذا قمت بالتثبيت من sdist) أو distlib (إذا قمت بالتثبيت من العجلة). لذلك يجب طلب أي إصلاح لهذه المشكلة من تلك المشاريع.

ولكن إذا كان هناك قيود على نظام التشغيل ، فربما يوجد ببساطة _ليس هناك حل قابل للتطبيق؟ يبدو أنني أتذكر أنه في وقت من الأوقات ، استخدم بيرل تعويذة سحرية لتنفيذ نصوص (googles قليلاً ...) نعم ، شيء من هذا القبيل (مترجم إلى Python)

#!/bin/sh
eval 'exec /the/long/interpreter/path/to/python $0 ${1+"$@"}'

ستحتاج إلى بعض الأشياء الإضافية حتى لا تحاول Python تنفيذ سطر EVAL-exec ، ولكن هذا قد ينجح.

إذا أراد أي شخص اقتراح شيء من هذا القبيل كطلب ميزة لـ setuptools و distlib ، فسيكون ذلك رائعًا.

لذلك ، عندما يصبح المسار ، إلى حيث يتم إنشاء python virtualenv ، طويلًا جدًا ، فلن يعمل استخدام نقطة virtualenv هذه.

سيكون من اللطيف _ حقًا_ تشغيل virtualenv على نظام تحدث فيه هذه المشكلة ، سيخرج الأمر بعض التحذير (أو حتى خطأ) من أن التواجد في دليل بهذا الاسم الطويل للمسار لا يدعمه أساسًا الافتراضات في الوقت الراهن.

أنا أضرب هذا أيضًا. إنها على وجه التحديد مشكلة بالنسبة لي لأنني أقوم بتشغيل pip من داخل تصميمات Jenkins ، والتي تحتوي على مسارات طويلة جدًا إلى pwd. ومن المثير للاهتمام ، أن لدي عددًا من عبيد الإنشاءات المتشابهة (تم ضبط جميع BINPRM_BUF_SIZE على 128 ، ونفس إصدارات pip و python و virtualenv) وأنا أواجه هذا على بعضها وليس على البعض الآخر ، حتى مع اختلاف أطوال المسار.

أحب اقتراح @ b-long ؛ إذا كان virtualenv سينشئ غلافًا لا يعمل على النظام الحالي ، فيجب على الأقل إعطاء المستخدم تحذيرًا ، إن لم يكن فشلًا تامًا.

ليس من الواضح كيف يمكن لـ virtualenv اكتشاف هذا الموقف. لا يمكننا استخدام قيمة بالضبط من رأس C ، ولا أعرف كيف اكتشفنا أننا على نظام بهذا القيد (Windows ليس لديه هذا القيد ، أليس كذلك OSX؟)

أنا أميل إلى إغلاق هذه المشكلة كقيود لنظام التشغيل ، وليست مشكلة virtualenv.

لما يستحق ، بعض الأفكار ...

  1. هل يستطيع ctypes فعل هذا؟
  2. ماذا عن شيء بسيط مثل:
# on Linux, BINPRM_BUF_SIZE == 128, giving us a maximum shebang length of 127
# 2 bytes for #!, 11 bytes for '/bin/python' leaves us with 114
if sys.platform() == 'Linux' and len(home_dir) > 114:
    log.warn("bin/activate may not work your system, as the length of the shebang line will exceed 128 characters")
  1. لا فكرة ، آسف.
  2. أنا من مستخدمي Windows وليس لدي رأي. إذا كنت تعتقد أن هذا معقول ، أقترح رفع العلاقات العامة ومعرفة رأي مستخدمي Linux ...

أنا متأكد من أن المستخدمين الآخرين سيقدرون التغيير الذي اقترحته. هل يمكننا ترك هذا مفتوحًا للتعليق ولإلهام العلاقات العامة؟ شكرا jantman و @ pfmoore : ابتسم:

يتم تعريف BINPRM_BUF_SIZE في رأس kernel ، ويبدو أنه يُستخدم فقط بواسطة عدد قليل من وظائف kernel. لا أعتقد أن هناك أي طريقة لاكتشاف ذلك برمجيًا (أقل من القراءة في الرؤوس ، وهو أمر غير ممكن في أي مكان).

ومع ذلك ، أعتقد أنه من المعقول افتراض أن هذا لن يتغير في أي وقت قريب (هناك نظرة عامة سريعة على الحد الأقصى لطول shebang هنا ). يتم أيضًا تحديد الطول الحالي بوضوح في قسم "الملاحظات" من صفحة الدليل execve (2) ، حيث ينص على أن "الحد الأقصى لطول السطر البالغ 127 حرفًا مسموح به للسطر الأول في #! برنامج نصي قابل للتنفيذ."

أفترض أن جميع أنظمة التشغيل المتوافقة مع POSIX لها حد من نوع ما ، على الرغم من أنه يبدو أن بعضها ، وتحديداً متغيرات BSD ، قد يكون لها حدود تزيد عن 8000 حرف.

على الرغم من أنه يبدو أنه سيكون حلاً معقولًا ببساطة كتابة شيء ما ساذجًا مثل اقتراحي أعلاه (إذا كان النظام الأساسي هو Linux وكان الخط أطول من 127 حرفًا) ، إلا أنه يبدو فظًا للغاية ومحددًا وغير مرن بالنسبة لي.

ما زلت أفكر في كيفية اختبار هذا برمجيًا بطريقة لا تضيف الكثير من النفقات العامة إلى virtualenv (ممنوح ، سنحتاج فقط إلى اختبار هذا في وقت إنشاء venv ، لذلك أنا ' د افترض أن بعض النفقات العامة قد تكون مقبولة).

لدي بعض كود إثبات المفهوم البسيط لاختبار ما إذا كان المسار المحدد هو طول مقبول أم لا ، لكنه قبيح إلى حد ما لأنه يكتب ملفًا على القرص ثم ينفذ الملف لالتقاط الإخراج. المثال والإخراج هنا: https://gist.github.com/jantman/ba39f98936643bc948bd

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

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

أن أكرر:

  1. الرجاء إرسال ملفات PR إلى setuptools و distlib إذا كنت تريد إصلاح هذا - الرمز ليس في virtualenv أو نقطة.
  2. لكي تكون مقبولة ، يجب أن تعمل التعليمات البرمجية على جميع الأنظمة الأساسية المدعومة ، بما في ذلك OSX و BSD ... وليس فقط Linux (الشروط الشرطية الخاصة بالنظام الأساسي مقبولة ، بالطبع ، إذا لم يكن هناك طريقة أخرى)

إغلاق هذه المشكلة ، لأنها ليست مشكلة virtualenv (يمكنك الحصول على نفس التأثير عن طريق تثبيت مترجم Python الكامل على اسم دليل طويل) ..

لقد ضربنا هذه المشكلة للتو.

لماذا لا تستخدم الثعبان من المسار؟ Virtualenv يسبقه بالفعل مع bin dir.

#!/usr/bin/env python

Virtualenv يسبقه بالفعل مع bin dir

فقط إذا قمت بتنشيط virtualenv. يدعم برنامج Virtualenv استخدامه بدون تنشيط.

إذا وجد أي شخص هذا مربكًا:

الحل البديل لهذه المشكلة هو عدم تشغيل pip مباشرةً ، ولكن عن طريق تشغيل مترجم python الخاص بـ virtualenv وتمرير نص النقطة إلى python كمصدر لتنفيذه.

هذا يعني أنه بدلاً من pip install -r requirements.txt افعل python -m pip install -r requirements.txt

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات