PYTHONPATH vs. sys.path

94

Pengembang lain dan saya tidak setuju tentang apakah PYTHONPATH atau sys.path harus digunakan untuk mengizinkan Python menemukan paket Python di direktori pengguna (misalnya, pengembangan).

Kami memiliki proyek Python dengan struktur direktori yang khas:

Project
    setup.py
    package
        __init__.py
        lib.py
        script.py

Di script.py, kita perlu melakukan import package.lib. Ketika paket diinstal di paket-situs, script.py dapat menemukan package.lib.

Namun, saat bekerja dari direktori pengguna, ada hal lain yang perlu dilakukan. Solusi saya adalah mengatur PYTHONPATH saya untuk menyertakan "~ / Project". Pengembang lain ingin meletakkan baris kode ini di awal script.py:

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

Sehingga Python dapat menemukan salinan lokal package.lib.

Saya pikir ini adalah ide yang buruk, karena baris ini hanya berguna untuk pengembang atau orang yang menjalankan dari salinan lokal, tetapi saya tidak dapat memberikan alasan yang baik mengapa ini adalah ide yang buruk.

Haruskah kita menggunakan PYTOHNPATH, sys.path, atau tidak masalah?

gaefan
sumber
4
Tampaknya suara dan jawaban dibagi secara merata dengan sedikit kecenderungan menggunakan PYTHON_PATH meskipun ini bisa berupa sampling noise atau bias yang tidak disengaja dari pertanyaan.
AJP
Untuk perbedaan antara PATHdan sys.path(dan secara tidak langsung PYTHONPATH) lihat juga stackoverflow.com/questions/25344841/sys-path-vs-path
tripleee

Jawaban:

42

Jika satu-satunya alasan untuk mengubah jalur adalah untuk pengembang yang bekerja dari pohon kerja mereka, maka Anda harus menggunakan alat instalasi untuk mengatur lingkungan Anda. virtualenv sangat populer, dan jika Anda menggunakan setuptools, Anda cukup menjalankan setup.py developsemi-install pohon kerja di instalasi Python Anda saat ini.

Ned Batchelder
sumber
11
Dapatkah Anda memberikan penjelasan lebih lanjut tentang ini? Bahkan jika Anda menggunakan lingkungan conda / virtualenv, bagaimana ini akan menempatkan direktori tingkat atas di jalur python Anda?
compguy24
38

Saya benci PYTHONPATH. Saya merasa rapuh dan menjengkelkan untuk mengatur per pengguna (terutama untuk pengguna daemon) dan melacak saat folder proyek bergerak. Saya lebih suka mengatur sys.pathskrip pemanggilan untuk proyek mandiri.

Namun sys.path.appendbukan cara melakukannya. Anda dapat dengan mudah mendapatkan duplikat, dan itu tidak memilah .pthfile. Lebih baik (dan lebih mudah dibaca): site.addsitedir.

Dan script.pybiasanya bukan tempat yang lebih tepat untuk melakukannya, karena ini ada di dalam paket yang ingin Anda sediakan di jalur. Modul perpustakaan seharusnya tidak menyentuh sys.pathdirinya sendiri. Sebagai gantinya, Anda biasanya memiliki skrip hashbanged di luar paket yang Anda gunakan untuk membuat instance dan menjalankan aplikasi, dan dalam skrip pembungkus sepele ini Anda akan meletakkan detail penerapan seperti sys.path-frobbing.

bobince
sumber
17
Masalahnya site.addsitediradalah bahwa ia tidak appendaktif sys.path, yang berarti bahwa paket yang diinstal akan didahulukan dari paket lokal yang sedang dikembangkan (dan mungkin terjadi penarikan rambut). sys.path.insert(0...dibutuhkan untuk mengatasinya.
Eli Bendersky
5
@EliBendersky: seharusnya sys.path.insert(1. stackoverflow.com/q/10095037/125507
endolith
12

Secara umum, saya akan mempertimbangkan untuk menyiapkan variabel lingkungan (seperti PYTHONPATH) sebagai praktik yang buruk. Meskipun ini mungkin baik-baik saja untuk debugging satu kali tetapi menggunakan ini sebagai
praktik biasa mungkin bukan ide yang baik.

Penggunaan variabel lingkungan mengarah ke situasi seperti "itu bekerja untuk saya" ketika ada orang
lain melaporkan masalah dalam basis kode. Juga seseorang mungkin melakukan praktik yang sama dengan lingkungan pengujian juga, yang mengarah ke situasi seperti pengujian yang berjalan dengan baik untuk pengembang tertentu tetapi mungkin gagal saat seseorang meluncurkan pengujian.

sateesh
sumber
6

Seiring dengan banyak alasan lain yang telah disebutkan, Anda juga bisa menunjukkan hard-coding itu

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

rapuh karena menganggap lokasi script.py - ini hanya akan bekerja jika script.py terletak di Proyek / package. Ini akan rusak jika pengguna memutuskan untuk memindahkan / copy / symlink script.py (hampir) ke tempat lain.

unutbu
sumber
5

Saya pikir, dalam kasus ini menggunakan PYTHONPATH adalah hal yang lebih baik, terutama karena tidak memasukkan kode yang tidak perlu (dipertanyakan).

Lagi pula, jika dipikir-pikir, pengguna Anda tidak membutuhkan sys.pathhal itu, karena paket Anda akan diinstal ke dalam paket situs, karena Anda akan menggunakan sistem pengemasan.

Jika pengguna memilih untuk menjalankan dari "salinan lokal", seperti yang Anda sebut, maka saya telah mengamati, bahwa praktik yang biasa adalah menyatakan, bahwa paket perlu ditambahkan ke PYTHONPATH secara manual, jika digunakan di luar paket situs .

shylent
sumber
3

Bukan peretasan PYTHONPATHjuga sys.pathbukan ide yang bagus karena alasan yang disebutkan sebelumnya. Dan untuk menautkan proyek saat ini ke folder paket situs sebenarnya ada cara yang lebih baik daripada python setup.py develop, seperti yang dijelaskan di sini :

pip install --editable path/to/project

Jika Anda belum memiliki setup.py di folder root proyek Anda, ini cukup baik untuk memulai dengan:

from setuptools import setup
setup('project')
Peter
sumber