Saya sedang menulis aplikasi Python yang mengambil sebagai perintah sebagai argumen, misalnya:
$ python myapp.py command1
Saya ingin aplikasi dapat dikembangkan, yaitu, untuk dapat menambahkan modul baru yang mengimplementasikan perintah baru tanpa harus mengubah sumber aplikasi utama. Pohon itu terlihat seperti:
myapp/
__init__.py
commands/
__init__.py
command1.py
command2.py
foo.py
bar.py
Jadi saya ingin aplikasi mencari modul perintah yang tersedia saat runtime dan menjalankan yang sesuai.
Python mendefinisikan fungsi __import__ , yang mengambil string untuk nama modul:
__import __ (nama, global = Tidak ada, penduduk setempat = Tidak ada, fromlist = (), level = 0)
Fungsi ini mengimpor nama modul, berpotensi menggunakan global dan lokal yang diberikan untuk menentukan cara menafsirkan nama dalam konteks paket. Thelistlist memberikan nama-nama objek atau submodul yang harus diimpor dari modul yang diberikan oleh nama.
Sumber: https://docs.python.org/3/library/functions.html# import
Jadi saat ini saya punya sesuatu seperti:
command = sys.argv[1]
try:
command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
# Display error message
command_module.run()
Ini berfungsi dengan baik, saya hanya ingin tahu apakah mungkin ada cara yang lebih idiomatis untuk mencapai apa yang kita lakukan dengan kode ini.
Perhatikan bahwa saya secara khusus tidak ingin menggunakan telur atau titik ekstensi. Ini bukan proyek open-source dan saya tidak berharap ada "plugin". Intinya adalah untuk menyederhanakan kode aplikasi utama dan menghapus kebutuhan untuk memodifikasinya setiap kali modul perintah baru ditambahkan.
sumber
dir(__import__)
. Daftar nama harus berupa daftar nama untuk ditiru "dari impor nama ...".importlib
: stackoverflow.com/a/54956419/687896Jawaban:
Dengan Python lebih tua dari 2,7 / 3.1, itu cukup banyak bagaimana Anda melakukannya.
Untuk versi yang lebih baru, lihat
importlib.import_module
untuk Python 2 dan dan Python 3 .Anda dapat menggunakannya
exec
jika Anda mau.Atau menggunakan
__import__
Anda dapat mengimpor daftar modul dengan melakukan ini:Merobek langsung dari Dive Into Python .
sumber
__init__
modul itu?__import__
. The 2.7 docs: "Karena fungsi ini dimaksudkan untuk digunakan oleh interpreter Python dan bukan untuk penggunaan umum, lebih baik menggunakan importlib.import_module () ..." Saat menggunakan python3,imp
modul memecahkan proble ini, seperti yang disebutkan oleh monkut di bawah ini.foreach
ketika Anda milikifor element in
danmap()
:) :)Cara yang disarankan untuk Python 2.7 dan 3.1 dan yang lebih baru adalah dengan menggunakan
importlib
modul:misalnya
sumber
__import__
fungsi yang mendukung modul yang disebutkan di atas.os.path
; bagaimanafrom os.path import *
?globals().update(my_module.__dict)
Seperti disebutkan modul imp memberikan Anda fungsi pemuatan:
Saya telah menggunakan ini sebelumnya untuk melakukan sesuatu yang serupa.
Dalam kasus saya, saya mendefinisikan kelas tertentu dengan metode yang ditentukan yang diperlukan. Setelah saya memuat modul saya akan memeriksa apakah kelas ada di modul, dan kemudian membuat instance dari kelas itu, sesuatu seperti ini:
sumber
expected_class
sehingga Anda bisa melakukannyaclass_inst = getattr(py_mod,expected_name)()
.Gunakan modul imp , atau fungsi yang lebih langsung
__import__()
.sumber
Saat ini Anda harus menggunakan importlib .
Impor file sumber
The docs benar-benar memberikan resep untuk itu, dan itu berjalan seperti:
Dengan cara ini Anda dapat mengakses anggota (misalnya, fungsi "
hello
") dari modul AndapluginX.py
- dalam cuplikan ini dipanggilmodule
- di bawah namespace-nya; Misalnyamodule.hello()
,.Jika Anda ingin mengimpor anggota (misalnya, "
hello
") Anda dapat memasukkanmodule
/pluginX
dalam daftar modul dalam memori:Impor paket
Mengimpor paket ( misalnya ,
pluginX/__init__.py
) di bawah dir Anda saat ini sebenarnya mudah:sumber
sys.modules[module_name] = module
ke akhir kode Anda jika Anda ingin dapatimport module_name
sesudahnyaJika Anda menginginkannya di lokal Anda:
sama akan bekerja dengan
globals()
sumber
locals()
fungsi eksplisit memperingatkan bahwa "isi kamus ini tidak harus diubah".Anda bisa menggunakan
exec
:sumber
as command_module
pada akhir pernyataan impor dan kemudian lakukancommand_module.run()
Mirip dengan solusi @monkut tetapi dapat digunakan kembali dan toleran terhadap kesalahan yang dijelaskan di sini http://stamat.wordpress.com/dynamic-module-import-in-python/ :
sumber
Bagian di bawah ini berfungsi untuk saya:
jika Anda ingin mengimpor skrip shell:
sumber
Sebagai contoh, nama modul saya seperti
jan_module
/feb_module
/mar_module
.sumber
Berikut ini bekerja untuk saya:
Ini memuat modul dari folder 'modus'. Modul memiliki satu kelas dengan nama yang sama dengan nama modul. Misalnya file mode / modu1.py berisi:
Hasilnya adalah daftar kelas "adapter" yang dimuat secara dinamis.
sumber
fl
? Definisi untuk loop terlalu rumit. Jalannya dikodekan dengan keras (dan sebagai contoh, tidak relevan). Ini menggunakan python berkecil hati (__import__
), untuk apa semua itufl[i]
? Ini pada dasarnya tidak dapat dibaca, dan tidak perlu rumit untuk sesuatu yang tidak terlalu sulit - lihat jawaban pilihan teratas dengan one-liner-nya.