Подтвердить что ты не робот

Импортировать модуль python без расширения .py

У меня есть файл foobar (без расширения .py). В том же каталоге у меня есть еще один файл python, который пытается его импортировать:

import foobar

Но это работает, только если я переименую файл в foobar.py. Возможно ли импортировать модуль python, который не имеет расширения .py?

Обновление: файл не имеет расширения, потому что я также использую его как автономный script, и я не хочу вводить расширение .py для его запуска.

Update2: я пойду для решения symlink, упомянутого ниже.

4b9b3361

Ответ 2

Как и другие, вы можете использовать imp.load_source, но это сделает ваш код более трудным для чтения. Я бы действительно рекомендовал его, если вам нужно импортировать модули, имена или пути которых неизвестны до времени выполнения.

В чем причина, почему вы не хотите использовать расширение .py? Наиболее распространенным случаем, когда вы не хотите использовать расширение .py, является то, что python script также запускается как исполняемый файл, но вы все еще хотите, чтобы другие модули могли его импортировать. Если это так, было бы полезно переместить функциональность в .py файл с похожим именем, а затем использовать foobar в качестве обертки.

Ответ 3

imp.load_source(module_name, path) должен сделать или вы можете сделать более подробный маршрут imp.load_module(module_name, file_handle, ...), если вместо этого есть дескриптор файла

Ответ 4

Вот решение для Python 3. 4+:

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

spec = spec_from_loader("foobar", SourceFileLoader("foobar", "/path/to/foobar"))
foobar = module_from_spec(spec)
spec.loader.exec_module(foobar)

Использование spec_from_loader и явное указание SourceFileLoader заставит механизм загружать файл как источник, не пытаясь определить тип файла по расширению. Это означает, что вы можете загрузить файл, даже если он не указан в importlib.machinery.SOURCE_SUFFIXES.

Если вы хотите продолжать импортировать файл по имени после первой загрузки, добавьте модуль в sys.modules:

sys.modules['foobar'] = foobar

Ответ 5

Если вы установите script с диспетчером пакетов (deb или аналогичным), другой вариант будет использовать setuptools:

"... нет простого способа, чтобы имя файла script s соответствовало локальным соглашениям на платформах Windows и POSIX. Для другого вам часто приходится создавать отдельный файл только для" основного "script когда ваш фактический" главный "является функцией в модуле где-то... setuptools исправляет все эти проблемы, автоматически генерируя для вас сценарии с правильным расширением, а в Windows он даже создаст файл .exe..."

https://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation

Ответ 6

вспомогательная функция importlib

Вот удобный, готовый к использованию помощник для замены imp на пример, основанный на том, что было упомянуто по адресу: fooobar.com/info/128850/...

main.py

#!/usr/bin/env python3

import os
import importlib

def import_path(path):
    module_name = os.path.basename(path).replace('-', '_')
    spec = importlib.util.spec_from_loader(
        module_name,
        importlib.machinery.SourceFileLoader(module_name, path)
    )
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    sys.modules[module_name] = module
    return module

notmain = import_path('not-main')
print(notmain)
print(notmain.x)

не магистральный

x = 1

Бежать:

python3 main.py

Выход:

<module 'not_main' from 'not-main'>
1

Я заменяю - на _ потому что мои импортируемые исполняемые файлы Python без расширения имеют дефисы. Это не обязательно, но дает лучшие имена модулей.

Этот шаблон также упоминается в документации по адресу: https://docs.python.org/3.7/library/importlib.html#importing-a-source-file-directly.

В итоге я перешел на него, потому что после обновления до Python 3.7 import imp:

DeprecationWarning: the imp module is deprecated in favour of importlib; see the module documentation for alternative uses

и я не знаю, как это отключить.

Протестировано в Python 3.7.3.