python pageobjects

subplot python



¿Forma pitónica de resolver sentencias de importación circulares? (3)

Por favor, lea la respuesta de Sebastian para una explicación detallada. Este enfoque fue propuesto por David Beazley en PyCon

Intenta posicionar las importaciones en la parte superior así.

try: from homePageLib import HomePage except ImportError: import sys HomePage = sys.modules[__package__ + ''.HomePage'']

Esto intentará importar tu HomePage y si falla, intentará cargarlo desde el caché

Acabo de heredar un código que me inquieta: hay una biblioteca de pruebas, llena de clases correspondientes a páginas web en nuestro sitio, y cada clase de página web tiene métodos para automatizar la funcionalidad en esa página.

Existen métodos para hacer clic en el enlace entre páginas, que devuelve la clase de la página vinculada. Aquí hay un ejemplo simplificado:

Archivo homePageLib.py archivo:

class HomePage(object): def clickCalendarLink(self): # Click page2 link which navigates browswer to page2 print "Click Calendar link" # Then returns the page2 object from calendarLib import CalendarPage return CalendarPage()

Archivo calendarLib.py:

class CalendarPage(object): def clickHomePageLink(self): # Click page1 link which navigates browswer to page1 print "Click Home Page link" # Then return the page2 object from homePageLib import HomePage return HomePage()

Esto permite que el archivo de script haga clic en las páginas y obtenga el objeto como un valor de retorno de ese método, lo que significa que el autor del script no tendrá que seguir creando una instancia de las páginas nuevas a medida que navegan por el sitio. (Siento que este es un diseño extraño, pero no puedo señalar exactamente por qué, aparte de eso, parece extraño tener un método llamado ''clickSomeLink'' y devolver un objeto de la página resultante).

La siguiente secuencia de comandos ilustra cómo una secuencia de comandos se desplazaría por el sitio: (inserté print page para mostrar cómo cambia el objeto de la página)

Archivo de comandos:

from homePageLib import HomePage page = HomePage() print page page = page.clickCalendarLink() print page page = page.clickHomePageLink() print page

que produce el siguiente resultado:

<homePageLib.HomePage object at 0x00B57570> Click Calendar link <calendarLib.CalendarPage object at 0x00B576F0> Click Home Page link <homePageLib.HomePage object at 0x00B57570>

Entonces, la parte de esto que más me incomoda específicamente es la from ____ import ____ líneas que terminan por todas partes. Estos me parecen malos por las siguientes razones:

  1. Siempre he hecho una convención para poner todas las declaraciones de importación en la parte superior de un archivo.
  2. Como puede haber varios enlaces a una página, esto se traduce en el mismo que en la línea de código de la from foo import bar en varios lugares de un archivo.

El problema es que si ponemos estas declaraciones de importación en la parte superior de la página, obtendremos errores de importación, porque (como en este ejemplo), HomePage importa CalendarPage y viceversa:

Archivo homePageLib.py

from calendarLib import CalendarPage class HomePage(object): def clickCalendarLink(self): # Click page2 link which navigates browswer to page2 print "Click Calendar link" # Then returns the page2 object return CalendarPage()

Archivo calendarLib.py

from homePageLib import HomePage class CalendarPage(object): def clickHomePageLink(self): # Click page1 link which navigates browswer to page1 print "Click Home Page link" # Then return the page2 object return HomePage()

Esto resulta en el siguiente error:

>>> from homePageLib import HomePage Traceback (most recent call last): File "c:/temp/script.py", line 1, in ? #Script File "c:/temp/homePageLib.py", line 2, in ? from calendarLib import CalendarPage File "c:/temp/calendarLib.py", line 2, in ? from homePageLib import HomePage ImportError: cannot import name HomePage

(consejos sobre cómo formatear mejor la salida de python?)

En lugar de perpetuar este estilo, me gustaría encontrar una mejor manera. ¿Hay alguna forma en Pythonic de lidiar con dependencias circulares como esta y aún así mantener las declaraciones de importación en la parte superior del archivo?


Resolver estos constructos usualmente involucra técnicas como la inyección de dependencia .

Sin embargo, es bastante simple corregir este error:

En calendarLib.py:

import homePageLib class CalendarPage(object): def clickHomePageLink(self): [...] return homePageLib.HomePage()

El código a nivel de módulo se ejecuta en el momento de la importación. El uso de la sintaxis from [...] import [...] requiere que el módulo se inicialice completamente para tener éxito.

Una simple import [...] no lo hace, porque no se accede a ningún símbolo, rompiendo así la cadena de dependencia.


Sí. Refactorizar para romper las cosas en piezas más pequeñas e independientes.