paquetes modulos lista python import

lista - modulos python



Importación desde la biblioteca interna cuando existe un módulo con el mismo nombre (5)

Cambiar la ruta de importación:

import sys save_path = sys.path[:] sys.path.remove('''') import calendar sys.path = save_path

Situación: - Hay un módulo en mi project_folder llamado calendar - Me gustaría utilizar la clase incorporada de Calendar de las bibliotecas de Python - Cuando lo uso desde Calendar import Calendar se queja porque está intentando cargar desde mi módulo.

He hecho algunas búsquedas y parece que no puedo encontrar una solución a mi problema.

¿Alguna idea sin tener que cambiar el nombre de mi módulo?


En realidad, resolver esto es bastante fácil, pero la implementación siempre será un poco frágil, ya que depende de las partes internas del mecanismo de importación de python y están sujetas a cambios en futuras versiones.

(el siguiente código muestra cómo cargar módulos locales y no locales y cómo pueden coexistir)

def import_non_local(name, custom_name=None): import imp, sys custom_name = custom_name or name f, pathname, desc = imp.find_module(name, sys.path[1:]) module = imp.load_module(custom_name, f, pathname, desc) f.close() return module # Import non-local module, use a custom name to differentiate it from local # This name is only used internally for identifying the module. We decide # the name in the local scope by assigning it to the variable calendar. calendar = import_non_local(''calendar'',''std_calendar'') # import local module normally, as calendar_local import calendar as calendar_local print calendar.Calendar print calendar_local

La mejor solución, si es posible, es evitar nombrar sus módulos con el mismo nombre que la biblioteca estándar o los nombres de los módulos integrados.


La única forma de resolver este problema es secuestrar la maquinaria interna de importación usted mismo. Esto no es fácil y está lleno de peligros. Debe evitar a toda costa el faro en forma de grial porque el peligro es demasiado peligroso.

Cambie el nombre de su módulo en su lugar.

Si desea aprender a secuestrar la maquinaria interna de importación, aquí es donde debería averiguar cómo hacer esto:

A veces hay buenas razones para entrar en este peligro. La razón por la que das no está entre ellos. Cambia el nombre de tu módulo.

Si tomas el camino peligroso, un problema que encontrarás es que cuando cargas un módulo termina con un ''nombre oficial'' para que Python pueda evitar tener que volver a analizar los contenidos de ese módulo. En sys.modules se puede encontrar un mapeo del "nombre oficial" de un módulo al objeto del módulo en sys.modules .

Esto significa que si import calendar en un lugar, se considerará que el módulo importado es el módulo con el calendar oficial y todos los demás intentos de import calendar cualquier otro lugar, incluso en otro código que forma parte de la biblioteca principal de Python. obtener ese calendario

Podría ser posible diseñar un importador de clientes utilizando el módulo imputil en Python 2.x que causó que los módulos cargados desde ciertas rutas sys.modules primero los módulos que estaban importando en algo que no sea sys.modules o algo así. Pero eso es algo extremadamente peludo de hacer, y de todos modos no funcionará en Python 3.x.

Hay algo extremadamente feo y horrible que puedes hacer que no implica enganchar el mecanismo de importación. Esto es algo que probablemente no debería hacer, pero probablemente funcionará. Convierte su módulo de calendar en un híbrido del módulo de calendario del sistema y su módulo de calendario. Gracias a por el esqueleto de la función que uso . Pon esto al comienzo de tu archivo calendar.py :

import sys def copy_in_standard_module_symbols(name, local_module): import imp for i in range(0, 100): random_name = ''random_name_%d'' % (i,) if random_name not in sys.modules: break else: random_name = None if random_name is None: raise RuntimeError("Couldn''t manufacture an unused module name.") f, pathname, desc = imp.find_module(name, sys.path[1:]) module = imp.load_module(random_name, f, pathname, desc) f.close() del sys.modules[random_name] for key in module.__dict__: if not hasattr(local_module, key): setattr(local_module, key, getattr(module, key)) copy_in_standard_module_symbols(''calendar'', sys.modules[copy_in_standard_module_symbols.__module__])


Me gustaría ofrecer mi versión, que es una combinación de la solución de Boaz Yaniv y Omnifarious. Importará la versión del sistema de un módulo, con dos diferencias principales de las respuestas anteriores:

  • Admite la notación ''punto'', p. Ej. paquete.modulo
  • Es un reemplazo directo para la declaración de importación en los módulos del sistema, lo que significa que solo tiene que reemplazar esa línea y si ya se están realizando llamadas al módulo, funcionarán tal cual.

Ponga esto en algún lugar accesible para que pueda llamarlo (tengo el mío en mi archivo __init__.py):

class SysModule(object): pass def import_non_local(name, local_module=None, path=None, full_name=None, accessor=SysModule()): import imp, sys, os path = path or sys.path[1:] if isinstance(path, basestring): path = [path] if ''.'' in name: package_name = name.split(''.'')[0] f, pathname, desc = imp.find_module(package_name, path) if pathname not in __path__: __path__.insert(0, pathname) imp.load_module(package_name, f, pathname, desc) v = import_non_local(''.''.join(name.split(''.'')[1:]), None, pathname, name, SysModule()) setattr(accessor, package_name, v) if local_module: for key in accessor.__dict__.keys(): setattr(local_module, key, getattr(accessor, key)) return accessor try: f, pathname, desc = imp.find_module(name, path) if pathname not in __path__: __path__.insert(0, pathname) module = imp.load_module(name, f, pathname, desc) setattr(accessor, name, module) if local_module: for key in accessor.__dict__.keys(): setattr(local_module, key, getattr(accessor, key)) return module return accessor finally: try: if f: f.close() except: pass

Ejemplo

Quería importar mysql.connection, pero tenía un paquete local que ya se llamaba mysql (las utilidades oficiales de mysql). Entonces, para obtener el conector del paquete mysql del sistema, lo reemplacé:

import mysql.connector

Con este:

import sys from mysql.utilities import import_non_local # where I put the above function (mysql/utilities/__init__.py) import_non_local(''mysql.connector'', sys.modules[__name__])

Resultado

# This unmodified line further down in the file now works just fine because mysql.connector has actually become part of the namespace self.db_conn = mysql.connector.connect(**parameters)


No es necesario cambiar el nombre de su módulo. Por el contrario, puede usar absolute_import para cambiar el comportamiento de importación. Por ejemplo, con stem/socket.py importo el módulo de socket de la siguiente manera:

from __future__ import absolute_import import socket

Esto solo funciona con Python 2.5 y superior; su comportamiento de habilitación es el predeterminado en Python 3.0 y superior. Pylint se quejará del código, pero es perfectamente válido.