Virtualenv: Panjang Shebang terlampaui dalam pip yang dapat dieksekusi

Dibuat pada 25 Apr 2014  ·  16Komentar  ·  Sumber: pypa/virtualenv

Ketika virtualenv baru dibuat, ada beberapa hal yang diinstal ke dalam virtualenv itu. Salah satunya adalah penginstal paket python, pip.

Di Linux, pip yang dapat dieksekusi adalah skrip shell. Di bagian atas skrip shell pip ini adalah baris Shebang (#!) yang menentukan interpreter python di virtualenv. Baris ini berisi path absolut ke interpreter python.

Jika jalur absolut ke juru bahasa python di virtualenv sangat panjang (sangat bersarang dan/atau nama jalur besar), itu mungkin melebihi panjang maksimum yang diizinkan untuk garis Shebang.

Panjang maksimum untuk baris shebang dibatasi di kernel oleh BINPRM_BUF_SIZE, diatur di /usr/include/linux/binfmts.h. Pada mesin Linux yang saya lihat, batas ini disetel ke 128.

Jadi, ketika jalur, ke tempat python virtualenv dibuat, menjadi terlalu panjang, menggunakan pip virtualenv itu tidak akan berfungsi. Itu akan gagal dengan kesalahan: "penerjemah buruk: Tidak ada file atau direktori seperti itu"

Solusi untuk masalah ini adalah tidak menjalankan pip secara langsung, tetapi dengan menjalankan penerjemah python virtualenv dan meneruskan skrip pip ke python sebagai sumber untuk dieksekusi.

Komentar yang paling membantu

Jika ada yang merasa ini membingungkan:

Solusi untuk masalah ini adalah tidak menjalankan pip secara langsung, tetapi dengan menjalankan penerjemah python virtualenv dan meneruskan skrip pip ke python sebagai sumber untuk dieksekusi.

Itu berarti alih-alih pip install -r requirements.txt lakukan python -m pip install -r requirements.txt

Semua 16 komentar

Saya juga mengalami masalah ini.

Gerakan mengungkap kekerasan seksual demi menghapuskannya.

Terima kasih atas solusinya!

Perhatikan bahwa skrip pembungkus sebenarnya dihasilkan oleh setuptools (jika Anda menginstal dari sdist) atau distlib (jika Anda menginstal dari roda). Jadi perbaikan apa pun untuk masalah ini harus benar-benar diminta dari proyek-proyek itu.

Tetapi jika itu adalah batasan OS, mungkin hanya ada _bukan_ perbaikan yang layak? Sepertinya saya ingat bahwa pada suatu waktu, Perl menggunakan mantra ajaib untuk mengeksekusi skrip (sedikit googles ...) Ya, sesuatu seperti ini (diterjemahkan untuk Python)

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

Anda memerlukan beberapa hal tambahan agar Python tidak mencoba mengeksekusi baris eval-exec, tetapi itu mungkin berhasil.

Jika ada yang ingin mengusulkan sesuatu seperti itu sebagai permintaan fitur untuk setuptools dan distlib, itu bagus.

Jadi, ketika jalur, ke tempat python virtualenv dibuat, menjadi terlalu panjang, menggunakan pip virtualenv itu tidak akan berfungsi.

Akan sangat _sangat_ menyenangkan jika menjalankan virtualenv pada sistem di mana masalah ini terjadi, perintah akan menampilkan beberapa peringatan (atau bahkan kesalahan) bahwa berada di direktori dengan nama jalur yang panjang pada dasarnya tidak didukung oleh default saat ini.

Saya memukul ini juga. Ini secara khusus menjadi masalah bagi saya karena saya menjalankan pip dari dalam build Jenkins, yang memiliki _sangat_ jalur panjang ke pwd. Menariknya, saya memiliki sejumlah budak build yang dibuat secara identik (semua memiliki BINPRM_BUF_SIZE diatur ke 128, dan versi pip dan python dan virtualenv yang sama) dan saya mengalami ini pada beberapa dari mereka tetapi tidak pada yang lain, bahkan dengan panjang jalur yang bervariasi.

Saya suka saran @b-long; jika virtualenv akan membuat pembungkus yang tidak berfungsi pada sistem saat ini, setidaknya itu harus memberi peringatan kepada pengguna, jika tidak gagal total.

Tidak jelas bagaimana virtualenv dapat mendeteksi situasi ini. Kami tidak dapat secara tepat menggunakan nilai dari header C, dan saya tidak tahu bagaimana kami mendeteksi bahwa kami berada di sistem dengan batasan ini (Windows tidak memilikinya, bukan OSX?)

Saya cenderung menutup masalah ini sebagai batasan OS, bukan masalah virtualenv.

Untuk apa nilainya, beberapa pemikiran ...

  1. dapatkah ctypes melakukan ini?
  2. Bagaimana dengan sesuatu yang sederhana seperti:
# 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. Tidak ada ide, maaf.
  2. Saya pengguna Windows jadi saya tidak punya pendapat. Jika menurut Anda ini masuk akal, saya sarankan untuk meningkatkan PR dan melihat apa yang dipikirkan orang-orang Linux ...

Saya yakin pengguna lain juga akan menghargai perubahan yang saya sarankan. Bisakah kita membiarkan ini terbuka untuk komentar dan menginspirasi PR? Terima kasih @jantman dan @pfmoore :smile:

BINPRM_BUF_SIZE didefinisikan dalam header kernel, dan tampaknya hanya digunakan oleh segelintir fungsi kernel. Saya tidak percaya ada cara untuk mendeteksi ini secara terprogram (singkat membaca di header, yang tidak mendekati layak).

Karena itu, saya pikir masuk akal untuk berasumsi bahwa ini tidak akan berubah dalam waktu dekat (ada ikhtisar singkat tentang panjang shebang maksimum di sini ). Panjang saat ini juga diberikan dengan jelas di bagian "Catatan" dari halaman manual execve(2) , yang menyatakan, "Panjang baris maksimum 127 karakter diperbolehkan untuk baris pertama dalam skrip shell #! yang dapat dieksekusi."

Saya akan berasumsi bahwa semua sistem operasi yang sesuai dengan POSIX memiliki batas, meskipun tampaknya beberapa di antaranya, khususnya varian BSD, mungkin memiliki batas hingga 8.000 karakter.

Meskipun sepertinya itu akan menjadi solusi yang masuk akal untuk hanya membuat kode keras sesuatu yang naif seperti saran saya di atas (jika platformnya adalah Linux dan garisnya lebih panjang dari 127 karakter), rasanya terlalu kasar dan spesifik dan tidak fleksibel bagi saya.

Saya masih memikirkan bagaimana saya akan menguji ini secara terprogram dengan cara yang tidak akan menambahkan terlalu banyak overhead ke virtualenv (memang, kami hanya perlu menguji ini pada waktu pembuatan venv, jadi saya' d menganggap beberapa overhead mungkin dapat diterima).

Saya memiliki beberapa kode proof-of-concept sederhana untuk menguji apakah jalur yang diberikan adalah panjang she-bang yang dapat diterima atau tidak, tetapi agak jelek karena ia menulis file ke disk dan kemudian mengeksekusi file untuk menangkap output. Contoh dan hasilnya ada di sini: https://Gist.github.com/jantman/ba39f98936643bc948bd

Saya harus menyebutnya malam, tetapi saya akan mencoba untuk kembali ke ini. Saya pasti akan menghargai masukan dari pengguna Linux lainnya, atau pengguna OS lain yang dapat mengkonfirmasi apakah mereka memiliki batasan yang sama atau tidak.

Alih-alih mencoba melakukan sesuatu yang rumit seperti membuat asumsi tentang batas, mengapa tidak membuat skrip bash uji fungsional saja? Jika python dipanggil dengan benar maka semuanya bagus, jika tidak, tidak.

Untuk mengulangi:

  1. Harap kirimkan PR ke setuptools dan distlib jika Anda ingin ini diperbaiki - kodenya tidak dalam virtualenv atau pip.
  2. Agar dapat diterima, kode harus bekerja pada semua platform yang didukung, termasuk OSX, BSD, ... dan bukan hanya Linux (syarat khusus platform dapat diterima, tentu saja, jika tidak ada cara lain)

Menutup masalah ini, karena ini bukan masalah virtualenv (Anda bisa mendapatkan efek yang sama dengan menginstal juru bahasa Python lengkap ke nama direktori yang panjang)..

Kami baru saja menyentuh masalah ini.

Mengapa tidak menggunakan python dari PATH? virtualenv sudah menambahkannya dengan dir bin.

#!/usr/bin/env python

virtualenv sudah menambahkannya dengan direktori bin

Hanya jika Anda mengaktifkan virtualenv. Virtualenv mendukung digunakan tanpa aktivasi.

Jika ada yang merasa ini membingungkan:

Solusi untuk masalah ini adalah tidak menjalankan pip secara langsung, tetapi dengan menjalankan penerjemah python virtualenv dan meneruskan skrip pip ke python sebagai sumber untuk dieksekusi.

Itu berarti alih-alih pip install -r requirements.txt lakukan python -m pip install -r requirements.txt

Apakah halaman ini membantu?
0 / 5 - 0 peringkat