Pertanyaan Bagaimana cara mengimpor modul yang diberikan jalur lengkap?


Bagaimana saya bisa memuat modul Python yang diberikan jalur lengkapnya? Perhatikan bahwa file dapat berada di mana saja di filesystem, karena ini adalah opsi konfigurasi.


774
2017-09-15 22:30


asal


Jawaban:


Untuk penggunaan Python 3,5+:

import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()

Untuk penggunaan Python 3.3 dan 3.4:

from importlib.machinery import SourceFileLoader

foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()

(Meskipun ini sudah ditinggalkan dalam Python 3.4.)

Penggunaan Python 2:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

Ada fungsi kenyamanan setara untuk file Python dikompilasi dan DLL.

Lihat juga. http://bugs.python.org/issue21436.


898
2017-09-15 22:41



Keuntungan menambahkan path ke sys.path (lebih dari menggunakan imp) adalah bahwa hal itu menyederhanakan hal ketika mengimpor lebih dari satu modul dari satu paket. Sebagai contoh:

import sys
# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py
sys.path.append('/foo/bar/mock-0.3.1')

from testcase import TestCase
from testutils import RunTests
from mock import Mock, sentinel, patch

307
2017-09-24 19:36



Anda juga dapat melakukan sesuatu seperti ini dan menambahkan direktori tempat file konfigurasi berada di jalur memuat Python, dan kemudian hanya melakukan impor normal, dengan asumsi Anda tahu nama file sebelumnya, dalam hal ini "config".

Berantakan, tapi itu berhasil.

configfile = '~/config.py'

import os
import sys

sys.path.append(os.path.dirname(os.path.expanduser(configfile)))

import config

17
2017-09-15 22:44



Anda dapat menggunakan

load_source(module_name, path_to_file) 

metode dari modul imp.


16
2017-09-15 22:41



Sepertinya Anda tidak ingin secara khusus mengimpor file konfigurasi (yang memiliki banyak sekali efek samping dan komplikasi tambahan yang terlibat), Anda hanya ingin menjalankannya, dan dapat mengakses ruang nama yang dihasilkan. Pustaka standar menyediakan API khusus untuk itu dalam bentuk runpy.run_path:

from runpy import run_path
settings = run_path("/path/to/file.py")

Antarmuka itu tersedia dalam Python 2.7 dan Python 3.2+


12
2018-05-20 06:52



def import_file(full_path_to_module):
    try:
        import os
        module_dir, module_file = os.path.split(full_path_to_module)
        module_name, module_ext = os.path.splitext(module_file)
        save_cwd = os.getcwd()
        os.chdir(module_dir)
        module_obj = __import__(module_name)
        module_obj.__file__ = full_path_to_module
        globals()[module_name] = module_obj
        os.chdir(save_cwd)
    except:
        raise ImportError

import_file('/home/somebody/somemodule.py')

10
2017-09-16 01:43



Maksud Anda memuat atau mengimpor?

Anda dapat memanipulasi daftar sys.path menentukan jalur ke modul Anda, lalu impor modul Anda. Misalnya, diberi modul di:

/foo/bar.py

Anda bisa melakukan:

import sys
sys.path[0:0] = '/foo' # puts the /foo directory at the start of your path
import bar

9
2017-09-15 22:46



Saya yakin Anda bisa menggunakannya imp.find_module() dan imp.load_module() memuat modul yang ditentukan. Anda harus memisahkan nama modul dari jalur, yaitu jika Anda ingin memuat /home/mypath/mymodule.py yang perlu Anda lakukan:

imp.find_module('mymodule', '/home/mypath/')

... tapi itu harus menyelesaikan pekerjaan.


8
2017-09-15 22:37



Berikut adalah beberapa kode yang bekerja di semua versi Python, dari 2.7-3.5 dan mungkin bahkan yang lain.

config_file = "/tmp/config.py"
with open(config_file) as f:
    code = compile(f.read(), config_file, 'exec')
    exec(code, globals(), locals())

Saya mengujinya. Ini mungkin jelek tapi sejauh ini adalah satu-satunya yang bekerja di semua versi.


7
2018-06-03 10:04



Saya telah datang dengan versi yang sedikit dimodifikasi dari jawaban indah @ SebastianRittau (untuk Python> 3.4 menurut saya), yang akan memungkinkan Anda untuk memuat file dengan ekstensi apa pun sebagai modul menggunakan spec_from_loader dari pada spec_from_file_location:

from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader 

spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py"))
mod = module_from_spec(spec)
spec.loader.exec_module(mod)

Keuntungan dari pengkodean jalan secara eksplisit SourceFileLoader Apakah itu mesin tidak akan mencoba mencari tahu jenis file dari ekstensi. Ini berarti Anda dapat memuat sesuatu seperti .txt file menggunakan metode ini, tetapi Anda tidak dapat melakukannya dengan spec_from_file_location tanpa menentukan loader karena .txt tidak ada importlib.machinery.SOURCE_SUFFIXES.


5
2018-04-25 05:45