Saat Anda menggunakan tanda -m
baris perintah , Python akan mengimpor modul atau paket untuk Anda, lalu menjalankannya sebagai skrip. Jika Anda tidak menggunakan -m
bendera, file yang Anda beri nama dijalankan hanya sebagai skrip .
Perbedaan ini penting saat Anda mencoba menjalankan sebuah paket. Ada perbedaan besar antara:
python foo/bar/baz.py
dan
python -m foo.bar.baz
seperti dalam kasus terakhir, foo.bar
diimpor dan impor relatif akan berfungsi dengan benar foo.bar
sebagai titik awal.
Demo:
$ mkdir -p test/foo/bar
$ touch test/foo/__init__.py
$ touch test/foo/bar/__init__.py
$ cat << EOF > test/foo/bar/baz.py
> if __name__ == "__main__":
> print __package__
> print __name__
>
> EOF
$ PYTHONPATH=test python test/foo/bar/baz.py
None
__main__
$ PYTHONPATH=test python -m foo.bar.baz
foo.bar
__main__
Akibatnya, Python harus benar-benar peduli dengan paket saat menggunakan -m
sakelar. Skrip normal tidak pernah bisa menjadi sebuah paket, jadi __package__
diatur ke None
.
Tetapi jalankan sebuah paket atau modul di dalam sebuah paket dengan -m
dan sekarang setidaknya ada kemungkinan sebuah paket, jadi __package__
variabel tersebut disetel ke nilai string; dalam demonstrasi di atas, ini disetel ke foo.bar
, untuk modul biasa yang tidak berada di dalam paket, ini disetel ke string kosong.
Adapun __main__
modulnya ; Skrip impor Python dijalankan seperti modul biasa. Objek modul baru dibuat untuk menampung namespace global, disimpan di sys.modules['__main__']
. Ini adalah apa yang __name__
dirujuk variabel, itu adalah kunci dalam struktur itu.
Untuk paket, Anda dapat membuat __main__.py
modul dan menjalankannya saat dijalankan python -m package_name
; sebenarnya itulah satu-satunya cara Anda dapat menjalankan paket sebagai skrip:
$ PYTHONPATH=test python -m foo.bar
python: No module named foo.bar.__main__; 'foo.bar' is a package and cannot be directly executed
$ cp test/foo/bar/baz.py test/foo/bar/__main__.py
$ PYTHONPATH=test python -m foo.bar
foo.bar
__main__
Jadi, saat menamai paket untuk dijalankan dengan -m
, Python mencari __main__
modul yang terdapat dalam paket itu dan menjalankannya sebagai skrip. Namanya kemudian masih disetel ke __main__
, dan objek modul masih disimpan di sys.modules['__main__']
.
PYTHONPATH=test python -m foo.bar
? Bisakah Anda menjelaskannya secara detail?PYTHONPATH
menetapkan variabel lingkungan; itu memperluas rangkaian direktori di mana Python akan mencari modul saat mengimpor; di sini ia menambahkantest
direktori ke seri tersebut. Dengan meletakkannya di baris perintah yang sama, ini hanya berlaku untuk satupython
perintah itu.-m
memberitahu Python untuk mengimpor modul tertentu, seolah-olah Anda berlariimport foo.bar
. Namun, Python akan secara otomatis menjalankan__main__
modul di dalam paket sebagai skrip saat Anda menggunakan sakelar itu.having to use -m always is not that user-.friendly.
Saya pikir campuran menggunakan dan tidak menggunakan-m
lebih ramah pengguna.-m
hanya berfungsi untuk direktori saat ini atau direktori yang sudah terdaftar di jalur pencarian. Itu maksud saya.-m
bukanlah sesuatu yang Anda berikan kepada pengguna akhir untuk masalah kegunaan itu.from Photos import ...
akan mengeluh. Begitu jugaimport Photos.<something>
.import Photos
hanya berfungsi karena Python mendukung paket dengan namespace (di mana dua distribusi terpisah menyediakanPhotos.foo
danPhotos.bar
secara terpisah dan mereka dapat dikelola secara independen).Eksekusi kode Python dengan opsi -m atau tidak
Gunakan
-m
benderanya.Hasilnya hampir sama ketika Anda memiliki skrip, tetapi ketika Anda mengembangkan sebuah paket, tanpa
-m
flag, tidak ada cara untuk membuat impor bekerja dengan benar jika Anda ingin menjalankan sub-paket atau modul dalam paket sebagai entri utama arahkan ke program Anda (dan percayalah, saya sudah mencoba.)Dokumen
Seperti dokumen di bendera -m yang mengatakan:
dan
begitu
kira-kira setara dengan
(dengan asumsi Anda tidak memiliki paket atau skrip di direktori Anda saat ini yang disebut pdb.py)
Penjelasan:
Perilaku dibuat "dengan sengaja mirip" dengan skrip.
Beberapa kode python dimaksudkan untuk dijalankan sebagai modul: (Saya pikir contoh ini lebih baik daripada contoh doc opsi baris perintah)
Dan dari sorotan catatan rilis untuk Python 2.4 :
Pertanyaan lanjutan
Artinya, setiap modul yang dapat Anda cari dengan pernyataan impor dapat dijalankan sebagai titik masuk program - jika memiliki blok kode, biasanya di dekat akhir, dengan
if __name__ == '__main__':
.-m
tanpa menambahkan direktori saat ini ke jalur:Sebuah komentar di sini di tempat lain mengatakan:
Nah, ini menunjukkan kemungkinan masalah - (di windows hapus tanda kutip):
Gunakan
-I
tanda tersebut untuk menguncinya untuk lingkungan produksi (baru di versi 3.4):dari dokumen :
Apa yang
__package__
dilakukannya?Ini memungkinkan impor relatif eksplisit, tidak terlalu terkait dengan pertanyaan ini, meskipun - lihat jawaban ini di sini: Apa tujuan dari atribut "__package__" di Python?
sumber
Alasan utama untuk menjalankan modul (atau paket) sebagai skrip dengan -m adalah untuk menyederhanakan penerapan, terutama di Windows. Anda dapat menginstal skrip di tempat yang sama di pustaka Python tempat modul biasanya ditempatkan - alih-alih mencemari PATH atau direktori global yang dapat dieksekusi seperti ~ / .local (direktori skrip per pengguna sangat sulit ditemukan di Windows).
Kemudian Anda cukup mengetik -m dan Python menemukan skripnya secara otomatis. Misalnya,
python -m pip
akan menemukan pip yang benar untuk instance interpreter Python yang sama yang mengeksekusinya. Tanpa -m, jika pengguna menginstal beberapa versi Python, manakah yang akan menjadi pip "global"?Jika pengguna lebih memilih titik masuk "klasik" untuk skrip baris perintah, ini dapat dengan mudah ditambahkan sebagai skrip kecil di suatu tempat di PATH, atau pip dapat membuatnya pada waktu penginstalan dengan parameter entry_points di setup.py.
Jadi periksa saja
__name__ == '__main__'
dan abaikan detail implementasi yang tidak dapat diandalkan lainnya.sumber