2010-04-08 12 views
42

Tengo un archivo llamado foobar (sin extensión .py). En el mismo directorio que tengo otro archivo de Python que intenta importarlo:Importar un módulo python sin la extensión .py

import foobar 

Pero esto sólo funciona si puedo cambiar el nombre del archivo a foobar.py. ¿Es posible importar un módulo python que no tenga la extensión .py?

Actualización: el archivo no tiene extensión porque también lo uso como una secuencia de comandos independiente, y no quiero escribir la extensión .py para ejecutarlo.

Update2: Iré por la solución de enlace simbólico que se menciona a continuación.

+1

estoy intrigado. ¿Por qué tienes un archivo de Python sin la extensión 'py'? – voyager

+1

A veces es bueno usar Python para archivos de configuración (extensión como .conf) o para denotar un tipo especial de archivo. En mi caso, sería más conveniente para un administrador. – NuclearPeon

+1

Tengo un archivo con una configuración que se usa como un archivo python y como un script bash. Le di una extensión 'pysh' ... – osa

Respuesta

31

Puede usar la función imp.load_source (desde el módulo imp), para cargar un módulo dinámicamente desde una ruta determinada del sistema de archivos.

foobar = imp.load_source('foobar', '/path/to/foobar') 

Este SO discussion también muestra algunas opciones interesantes.

+0

Fixed. [es más constructivo sugerir una Edición, aunque] –

+0

pero de nuevo se requiere sección como entendí de >>> foobar = imp.load_source ('', 'credentials') [predeterminado] NameError: name 'default' no está definido – Ilja

+2

¿Para qué sirve el primer argumento ''foobar'' si está asignado en el valor de retorno? –

13

imp.load_source(module_name, path) debe hacer o puede hacer lo imp.load_module(module_name, file_handle, ...) ruta más detallada si tiene un identificador de archivo en lugar

13

Como otros han mencionado, se puede usar imp.load_source, sino que hará que el código sea más difícil de leer. Realmente lo recomendaría solo si necesita importar módulos cuyos nombres o rutas no se conocen hasta el tiempo de ejecución.

¿Cuál es el motivo por el que no desea utilizar la extensión .py? El caso más común para no querer usar la extensión .py es que el script de python también se ejecuta como un archivo ejecutable, pero aún desea que otros módulos lo puedan importar. Si este es el caso, podría ser beneficioso mover la funcionalidad a un archivo .py con un nombre similar, y luego usar foobar como un contenedor.

+12

O en lugar de envolver, solo enlace simbólico foobar.py a foobar (suponiendo que no esté en Windows) – whaley

+0

@whaley, sí, eso sería mucho más limpio. Puede usar un .bat para Windows para lograr lo mismo. –

+0

Tengo un buen caso de uso, un archivo Léame, con ejemplos, que me gustaría más validar. Espero hacer un doctest markdown doc que funcione ... –

1

Si instala el guión con el gestor de paquetes (deb o similar) otra opción sería utilizar setuptools:

"...there’s no easy way to have a script’s filename match local conventions on both Windows and POSIX platforms. For another, you often have to create a separate file just for the “main” script, when your actual “main” is a function in a module somewhere... setuptools fixes all of these problems by automatically generating scripts for you with the correct extension, and on Windows it will even create an .exe file..."

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

4

Aquí es una solución para 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) 

El uso de spec_from_loader y la especificación explícita de SourceFileLoader obligará al machinery a cargar el archivo s fuente, sin tratar de averiguar el tipo de archivo de la extensión. Esto significa que puede cargar el archivo aunque no aparezca en importlib.machinery.SOURCE_SUFFIXES.

Si desea mantener la importación del archivo por su nombre después de la primera carga, agregar el módulo a sys.modules:

sys.modules['foobar'] = foobar 
Cuestiones relacionadas