Categorías
Python

Leer y escribir archivos CSV

 

Tabla de Contenidos

  • Introducción a Pruebas en DjangoTypes de paquetes practicesStructureThird partes testsBest
  • Tipos de pruebas
  • Mejor practica paquetes Estructura
  • de terceros
  • ExamplesSetupTesting ModelsTesting ViewsTesting FormsTesting la API
  • Configuración
  • Prueba

  • modelos
  • Prueba

  • Vistas
  • Prueba

  • Formularios
  • Prueba

  • las API
  • la próxima vez
  • Tipos de pruebas de paquetes
  • de terceros
  • mejores prácticas
  • Estructura del setup
  • modelos
  • Testing

  • Testing

  • vistas
  • Prueba

  • Formularios
  • Prueba

  • la API

Prueba

es vital. Sin probar correctamente su código, que nunca se sabe si el código funciona como debería, ahora o en el futuro, cuando los cambios de código base. Incontables horas se pueden perder la solución de problemas causados ​​por cambios en el código base. Lo que es peor, puede que ni siquiera sabe que hay problemas en absoluto hasta los usuarios finales se quejan de ello, que obviamente no es la forma en que desea averiguar sobre descansos de código.

Tener pruebas en lugar será ayuda asegurar que si se rompe una función específica va a saber de él. Las pruebas también hacen que la depuración se rompe en el código mucho más fácil, lo que ahorra tiempo y dinero.

He perdido literalmente conciertos en el pasado de no probar nuevas funciones adecuadamente contra el antiguo código base. No dejes que esto te pase. Tome la prueba en serio. Va a tener más confianza en su código, y su empleador tendrá más confianza en usted. Básicamente se trata de una póliza de seguro.

Prueba ayuda estruturas buen código, encontrar errores y documentación de escritura.

En este post, vamos a estar mirando primero una introducción breve que incluye las mejores prácticas antes de mirar algunos ejemplos. Bono

gratuito: Haga clic aquí para obtener acceso a una guía gratuita Django Recursos de Aprendizaje (PDF) que le muestra sugerencias y trucos, así como los errores comunes a evitar al crear aplicaciones web Python + Django.

Introducción a Prueba de Django

Tipos de pruebas Unidad

y la integración son los dos principales tipos de pruebas: pruebas unitarias

    • están aislados pruebas que ponen a prueba una función específica. Las pruebas
    • de integración, por su parte, son las pruebas más grandes que se centran en el comportamiento del usuario y probar aplicaciones enteras. Dicho de otra manera, las pruebas de integración combina diferentes piezas de funcionalidad código para asegurarse de que se comportan correctamente.

    Centrarse en las pruebas unitarias. Escribir un montón de éstos. Estas pruebas son mucho más fáciles de escribir y pruebas de integración de depuración frente, y cuanto más se tenga, menos pruebas de integración que va a necesitar. Las pruebas unitarias deben ser rápidos. Vamos a ver algunas técnicas para acelerar las pruebas.

    Dicho esto, las pruebas de integración son a veces todavía necesario incluso si tiene cobertura con pruebas unitarias, ya que las pruebas de integración pueden ayudar a regresiones código de captura.

    En general, las pruebas de resultado ya sea en un éxito (resultados esperados), insuficiencia (resultados inesperados), o un error. No sólo es necesario para la prueba de los resultados esperados, sino también qué tan bien su código controla resultados inesperados.

    Mejor practica

    • actualizar localmente,
    • ejecutar el conjunto de pruebas, arreglar errores
    • , PUSH
    • al repositorio y puesta en escena, y luego prueba
    • de nuevo en la organización antes de enviar el código. Estructura

    Estructura

    sus pruebas para adaptarse a su proyecto. Me inclino a favor de poner todas las pruebas para cada aplicación en el archivo tests.py y agrupar las pruebas por lo que estoy probando – por ejemplo, modelos, vistas, formularios, etc.

    También se puede derivar (eliminar) las pruebas archivo .py por completo y estructurar sus pruebas de esta manera dentro de cada aplicación:

    └── app_name
    └── tests
    ├── __init__.py
    ├── test_forms.py
    ├── test_models.py
    └── test_views.py

    por último, se podría crear una carpeta de prueba independiente, que refleja toda la estructura del proyecto, la colocación de un archivo tests.py en cada carpeta de aplicación.

    proyectos más grandes deben utilizar una de las últimas estructuras. Si sabe que su proyecto más pequeño con el tiempo se escala en algo mucho más grande, lo mejor es utilizar una de las dos últimas estructuras también. Estoy a favor de la primera y la tercera estructuras, ya que me resulta más fácil diseñar pruebas para cada aplicación cuando todos ellos son visibles en una secuencia de comandos. Los paquetes de terceros

    Use los siguientes paquetes y bibliotecas para ayudar con la escritura y el funcionamiento de su banco de pruebas:

    • django-webtest: hace que sea mucho más fácil de escribir pruebas funcionales y afirmaciones que coinciden con la experiencia del usuario final. La combinación de estas pruebas con las pruebas de Selenium para una cobertura total en las plantillas y puntos de vista. la cobertura
    • : se utiliza para medir la efectividad de las pruebas, que muestra el porcentaje de su base de código cubierto por las pruebas. Si usted apenas está comenzando a establecer las pruebas de unidad, la cobertura puede ayudar a ofrecer sugerencias sobre lo que debe ser probado. La cobertura también se puede utilizar para convertir la prueba en un juego: Trato de aumentar el porcentaje de código cubierto por las pruebas de cada día, por ejemplo.
    • django-descubrir-corredor: ayuda a localizar las pruebas si se organizan de una manera diferente (por ejemplo, fuera del tests.py). Así que si a organizar sus pruebas en carpetas separadas, como en el ejemplo anterior, puede utilizar descubrir favorito para localizar las pruebas. factory_boy
    • , model_mommy, y mock: todo se utilizan en lugar de los accesorios o la ORM para poblar los datos necesarios para la prueba. Ambas instalaciones y el ORM puede ser lento y necesitan ser actualizados cada vez que cambia su modelo.

    Ejemplos

    En este ejemplo básico, que estarán probando: modelos

    • , vistas
    • , formas
    • , y
    • la API.

    Descargar el Github repo aquí para seguir a lo largo. Configuración

    Instalar cobertura y agregarlo a su INSTALLED_APPS: cobertura

    $ pip install coverage==3.6

    Run:

    $ coverage run manage.py test whatever -v 2

    uso nivel de verbosidad 2, -v 2, para más detalles. También puede probar su proyecto Django a la vez con este comando: cobertura de ejecutar la prueba manage.py -v 2.

    elaborar su propio informe para ver dónde debe comenzar la prueba:

    $ coverage html

    abierto django15 / htmlcov / index.html a ver los resultados de su informe. Desplazarse hasta la parte inferior del informe. Puede omitir todas las filas de la carpeta virtualenv. Nunca prueba de cualquier cosa que es una función integrada de Python o biblioteca ya los que ya se ponen a prueba. Puede mover su virtualenv fuera de la carpeta para hacer que el limpiador de informe después de que corrió. inicio de

    Let probando los modelos. Modelos de prueba

    Dentro del informe de cobertura, haga clic en el enlace para “Lo / modelos”. Usted debe ver esta pantalla:

    En esencia, este informe se indica que hay que probar el título de una entrada. Sencillo.

    abierto tests.py y agregue el siguiente código:

    from django.test import TestCase
    from whatever.models import Whatever
    from django.utils import timezone
    from django.core.urlresolvers import reverse
    from whatever.forms import WhateverForm

    # models test
    class WhateverTest(TestCase):

    def create_whatever(self, title="only a test", body="yes, this is only a test"):
    return Whatever.objects.create(title=title, body=body, created_at=timezone.now())

    def test_whatever_creation(self):
    w = self.create_whatever()
    self.assertTrue(isinstance(w, Whatever))
    self.assertEqual(w.__unicode__(), w.title)

    lo que está pasando aquí? Hemos creado esencialmente un objeto cualquiera y probó si el título creado emparejado el título de esperar – lo que hizo.

    Nota: asegúrese de que sus nombres de función comience con test, que no sólo es una convención común sino también para que Django-descubrir-corredor puede localizar la prueba. Además, las pruebas de escritura para todos de los métodos que se suman a su modelo. la cobertura de gestión Re

    :

    $ coverage run manage.py test whatever -v 2

    debería ver los siguientes resultados, indicando la prueba se ha superado:

    test_whatever_creation (whatever.tests.WhateverTest) ... ok

    ----------------------------------------------------------------------
    Ran 1 test in 0.002s

    OK

    Entonces, si nos fijamos en el informe de la cobertura de nuevo, los modelos debe ahora estar al 100%.

    Prueba

    Vistas Vistas

    Testing

    a veces puede ser difícil. Yo generalmente uso unidad de pruebas para comprobar los códigos de estado, así como selenio WebDriver para probar AJAX, Javascript, etc.

    Agregue el código siguiente a la clase WhateverTest en tests.py :

    # views (uses reverse)

    def test_whatever_list_view(self):
    w = self.create_whatever()
    url = reverse("whatever.views.whatever")
    resp = self.client.get(url)

    self.assertEqual(resp.status_code, 200)
    self.assertIn(w.title, resp.content)

    Aquí buscamos a la URL del cliente , almacenar los resultados en la variable resp y luego probar nuestras afirmaciones. En primer lugar, comprobamos si el código de respuesta es 200, y luego probamos la parte posterior de respuesta real. Usted debe obtener resultados thefollowing:

    test_whatever_creation (whatever.tests.WhateverTest) ... ok
    test_whatever_list_view (whatever.tests.WhateverTest) ... ok

    ----------------------------------------------------------------------
    Ran 2 tests in 0.052s

    OK

    Ejecutar el informe de nuevo. Ahora debería ver un enlace para “Lo / puntos de vista”, que muestra los siguientes resultados:

    Puede también pruebas de escritura para asegurarse de que algo falla. Por ejemplo, si un usuario necesita que estar conectado para crear un nuevo objeto, la prueba tendría éxito si en realidad no puede crear el objeto. La mirada de

    Veamos una prueba rápida de selenio:

    # views (uses selenium)

    import unittest
    from selenium import webdriver

    class TestSignup(unittest.TestCase):

    def setUp(self):
    self.driver = webdriver.Firefox()

    def test_signup_fire(self):
    self.driver.get("http://localhost:8000/add/")
    self.driver.find_element_by_id('id_title').send_keys("test title")
    self.driver.find_element_by_id('id_body').send_keys("test body")
    self.driver.find_element_by_id('submit').click()
    self.assertIn("http://localhost:8000/", self.driver.current_url)

    def tearDown(self):
    self.driver.quit

    if __name__ == '__main__':
    unittest.main()

    Instalar el selenio:

    $ pip install selenium==2.33.0

    Ejecutar las pruebas. Firefox se debe cargar (si lo tienes instalado) y ejecute la prueba. a continuación, afirmamos que la página se carga correcta tras la presentación. También puede comprobar para asegurarse de que el nuevo objeto se agrega a la base de datos.

    Prueba

    Formularios

    Añadir los siguientes métodos:

    def test_valid_form(self):
    w = Whatever.objects.create(title='Foo', body='Bar')
    data = {'title': w.title, 'body': w.body,}
    form = WhateverForm(data=data)
    self.assertTrue(form.is_valid())

    def test_invalid_form(self):
    w = Whatever.objects.create(title='Foo', body='')
    data = {'title': w.title, 'body': w.body,}
    form = WhateverForm(data=data)
    self.assertFalse(form.is_valid())

    Aviso la forma en que están generando los datos de la forma de JSON. Este es un accesorio.

    Ahora debe tener 5 pruebas que pasan:

    test_signup_fire (whatever.tests.TestSignup) ... ok
    test_invalid_form (whatever.tests.WhateverTest) ... ok
    test_valid_form (whatever.tests.WhateverTest) ... ok
    test_whatever_creation (whatever.tests.WhateverTest) ... ok
    test_whatever_list_view (whatever.tests.WhateverTest) ... ok

    ----------------------------------------------------------------------
    Ran 5 tests in 12.753s

    OK

    Usted podría también pruebas de escritura que afirmar si se muestra un mensaje de error determinado en base a los validadores en el propio formulario.

    Prueba

    la API

    En primer lugar, se puede acceder a la API desde esta dirección: http: // localhost: 8000 / api lo / formato / = JSON. Esta es una configuración sencilla, por lo que las pruebas serán bastante simple también.

    Instalar lxml y XML desactivado:

    $ pip install lxml==3.2.3
    $ pip install defusedxml==0.4.1

    Añadir los siguientes casos de prueba:

    from tastypie.test import ResourceTestCase

    class EntryResourceTest(ResourceTestCase):

    def test_get_api_json(self):
    resp = self.api_client.get('/api/whatever/', format='json')
    self.assertValidJSONResponse(resp)

    def test_get_api_xml(self):
    resp = self.api_client.get('/api/whatever/', format='xml')
    self.assertValidXMLResponse(resp)

    Simplemente estamos afirmando que obtenemos una respuesta en cada caso.

    la próxima vez

    En el siguiente tutorial, vamos a encontrar un ejemplo más complicado, así como el uso de model_mommy para la generación de datos de prueba. Una vez más, se puede agarrar el código desde el repositorio. Bono

    gratuito: Haga clic aquí para obtener acceso a una guía gratuita Django Recursos de Aprendizaje (PDF) que le muestra sugerencias y trucos, así como los errores comunes a evitar al crear aplicaciones web Python + Django.

    Tienes algo que añadir? Deja un comentario más abajo.

  • Categorías
    Python

    Versiones de ejecución de Python en acoplable: Cómo probar la última Release Python

     

    Tabla de Contenidos

    • Instalación Requisitos
    • configuración de actualización de
    • modelo de datos
    • local Migración
    • remoto Migración
    • Conclusión

    En esta parte vamos a establecer una base de datos PostgreSQL para almacenar los resultados de nuestras cuentas de la palabra, así como SQLAlchemy, un objeto relacional Mapper, y Alambique a las migraciones de bases de datos mango. Bono

    gratuito: Haga clic aquí para obtener acceso a un tutorial de vídeo libres Frasco + Python que muestra cómo construir aplicación web Frasco, paso a paso.

    Actualizaciones :

    • 22/03/2016: actualizado a la versión 3.5.1 de Python, así como las últimas versiones de psycopg2, Frasco-SQLAlchemy y matraz de migrar. Véase más abajo para más detalles.
    • 02/22/2015: Agregado Python 3 apoyo.

    Recuerde: Esto es lo que estamos construyendo – Un Frasco aplicación que calcula pares de palabras de frecuencia basado en el texto de una determinada URL.

    Need el código? Agarrarlo desde el repositorio.

    Requerimientos de Instalación Herramientas

    utilizados en esta parte:

    • PostgreSQL (9.4)
    • psycopg2 (2.6.1) – un adaptador de Python para Postgres
    • matraz de SQLAlchemy (2.1) – Frasco extensión que proporciona soporte SQLAlchemy
    • matraz de migración (1.8.0) – extensión que soporta SQLAlchemy migraciones de bases de datos a través del alambique

    Para empezar, instalar Postgres en su computadora local, si no lo tiene ya. Desde Heroku utiliza PostgreSQL, que será bueno para nosotros desarrollar localmente en la misma base de datos. Si no tiene instalado Postgres, Postgres.app es una manera fácil de poner en marcha para los usuarios de Mac OS X. Consulte la página de descarga para obtener más información.

    Una vez que se han instalado Postgres y funcionando, crear una base de datos llamada wordcount_dev utilizar como nuestra base de datos de desarrollo local:

    $ psql
    # create database wordcount_dev;
    CREATE DATABASE
    # \q

    Para poder utilizar nuestra base de datos de nueva creación dentro de la aplicación frasco que a necesidad de instalar un par de cosas:

    $ cd flask-by-example

    cding en el directorio debe activar el entorno virtual y establecer las variables de entorno encontraron en el archivo .env través autoenv, que hemos creado en la parte 1.

    $ pip install psycopg2==2.6.1 Flask-SQLAlchemy===2.1 Flask-Migrate==1.8.0
    $ pip freeze > requirements.txt

    Si estás en OS X y que tiene verificación de la instalación psycopg2 problemas a cabo este Pila Artículo desbordamiento.

    configuración de actualización de

    Añadir campo SQLALCHEMY_DATABASE_URI a la clase Config () en el archivo config.py a configurar su aplicación para utilizar la base de datos de nueva creación en el desarrollo (local), puesta en escena, y la producción:

    import os

    class Config(object):
    ...
    SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']

    Su configuración archivo .py ahora debería tener este aspecto:

    import os
    basedir = os.path.abspath(os.path.dirname(__file__))

    class Config(object):
    DEBUG = False
    TESTING = False
    CSRF_ENABLED = True
    SECRET_KEY = 'this-really-needs-to-be-changed'
    SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']

    class ProductionConfig(Config):
    DEBUG = False

    class StagingConfig(Config):
    DEVELOPMENT = True
    DEBUG = True

    class DevelopmentConfig(Config):
    DEVELOPMENT = True
    DEBUG = True

    class TestingConfig(Config):
    TESTING = True

    ahora, cuando nuestra configuración se carga en nuestra aplicación de la base de datos correspondiente se conectará a él también.

    Similar a como hemos añadido una variable de entorno en el último post, vamos a añadir una variable DATABASE_URL. Ejecutar este en el terminal:

    $ export DATABASE_URL="postgresql://localhost/wordcount_dev"

    Y luego añadir que la línea en el archivo su .env.

    En su app.py archivo de importación SQLAlchemy y de conexión a la base de datos:

    from flask import Flask
    from flask.ext.sqlalchemy import SQLAlchemy
    import os

    app = Flask(__name__)
    app.config.from_object(os.environ['APP_SETTINGS'])
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    db = SQLAlchemy(app)

    from models import Result

    @app.route('/')
    def hello():
    return "Hello World!"

    @app.route('/')
    def hello_name(name):
    return "Hello {}!".format(name)

    if __name__ == '__main__':
    app.run()

    modelo de datos

    Conjunto de un modelo de base, añadiendo un archivo models.py :

    from app import db
    from sqlalchemy.dialects.postgresql import JSON

    class Result(db.Model):
    __tablename__ = 'results'

    id = db.Column(db.Integer, primary_key=True)
    url = db.Column(db.String())
    result_all = db.Column(JSON)
    result_no_stop_words = db.Column(JSON)

    def __init__(self, url, result_all, result_no_stop_words):
    self.url = url
    self.result_all = result_all
    self.result_no_stop_words = result_no_stop_words

    def __repr__(self):
    return ''.format(self.id)

    Aquí hemos creado una tabla para almacenar los resultados de las palabra cuenta.

    Primero importar la conexión de base de datos que hemos creado en nuestro archivo app.py , así como JSON de dialectos de PostgreSQL SQLAlchemy. JSON columnas son bastante nuevo en Postgres y no están disponibles en cada base de datos soportado por SQLAlchemy por lo que necesitamos para importar específicamente.

    A continuación creamos una clase Resultado () y le asignó el nombre de una tabla de resultados. A continuación, establecemos los atributos que queremos almacenar para un result-

    • el identificador del resultado que nos guardaron
    • la url que contamos con las palabras de
    • una lista completa de palabras que contamos
    • una lista de palabras que contamos con las palabras vacías menos (más sobre esto más adelante)

    a continuación, creamos un () método __init __ que se ejecutará la primera vez que creamos un nuevo resultado y el método, por último, una __repr __ () para representar el objeto cuando nos consulta para ello.

    local Migración

    Vamos a utilizar Alambique, que forma parte del matraz de Migración, para gestionar las migraciones de bases de datos para actualizar el esquema de una base de datos.

    Crear un nuevo archivo llamado manage.py :

    import os
    from flask.ext.script import Manager
    from flask.ext.migrate import Migrate, MigrateCommand

    from app import app, db

    app.config.from_object(os.environ['APP_SETTINGS'])

    migrate = Migrate(app, db)
    manager = Manager(app)

    manager.add_command('db', MigrateCommand)

    if __name__ == '__main__':
    manager.run()

    Para utilizar matraz de Migración nos importó Gestor, así como migrar y MigrateCommand a nuestro archivo manage.py . También hemos importado aplicación y db por lo que tenemos acceso a ellos desde dentro del script.

    En primer lugar, hemos establecido nuestra config para conseguir nuestro medio ambiente – en base a la variable de entorno – creado una instancia de migración, la aplicación y el PP como los argumentos, y estableció un comando encargado de inicializar una instancia de Manager para nuestra aplicación. Por último, agregamos el comando db con el gerente para que podamos ejecutar las migraciones desde la línea de comandos.

    Con el fin de ejecutar las migraciones inicializar Alambique:

    $ python manage.py db init
    Creating directory /flask-by-example/migrations ... done
    Creating directory /flask-by-example/migrations/versions ... done
    Generating /flask-by-example/migrations/alembic.ini ... done
    Generating /flask-by-example/migrations/env.py ... done
    Generating /flask-by-example/migrations/README ... done
    Generating /flask-by-example/migrations/script.py.mako ... done
    Please edit configuration/connection/logging settings in
    '/flask-by-example/migrations/alembic.ini' before proceeding.

    Después de ejecutar la base de datos de inicialización, verá una nueva carpeta llamada “migraciones” en el proyecto. Esto es necesario para la configuración del alambique a las migraciones dirigidas contra el proyecto. Dentro de las “migraciones” verá que tiene una carpeta llamada “versiones”, que contendrá los scripts de migración a medida que se crean.

    Vamos a crear nuestra primera migración mediante la ejecución del comando migrate.

    $ python manage.py db migrate
    INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
    INFO [alembic.runtime.migration] Will assume transactional DDL.
    INFO [alembic.autogenerate.compare] Detected added table 'results'
    Generating /flask-by-example/migrations/versions/63dba2060f71_.py
    ... done

    Ahora se dará cuenta de sus “versiones” carpeta hay un archivo de migración. Este archivo es por Alambique basado en el modelo de auto-generado. Se podría generar (o editar) este archivo usted mismo; Sin embargo, para la mayoría de los casos va a hacer el archivo generado automáticamente.

    Ahora vamos a aplicar las mejoras a la base de datos utilizando el comando de actualización db:

    $ python manage.py db upgrade
    INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
    INFO [alembic.runtime.migration] Will assume transactional DDL.
    INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message

    La base de datos está ahora lista para usarla en nuestra aplicación:

    $ psql
    # \c wordcount_dev
    You are now connected to database "wordcount_dev" as user "michaelherman".
    # \dt

    List of relations
    Schema | Name | Type | Owner
    --------+-----------------+-------+---------------
    public | alembic_version | table | michaelherman
    public | results | table | michaelherman
    (2 rows)

    # \d results
    Table "public.results"
    Column | Type | Modifiers
    ----------------------+-------------------+------------------------------------------------------
    id | integer | not null default nextval('results_id_seq'::regclass)
    url | character varying |
    result_all | json |
    result_no_stop_words | json |
    Indexes:
    "results_pkey" PRIMARY KEY, btree (id)

    remoto Migración

    Por último, vamos a aplicar las migraciones a las bases de datos en Heroku. En primer lugar, sin embargo, tenemos que añadir los detalles de las bases de datos de ensayo y producción en el fichero de config.py . cheque

    Para si tenemos una base de datos creada en la carrera servidor de ensayo:

    $ heroku config --app wordcount-stage
    === wordcount-stage Config Vars
    APP_SETTINGS: config.StagingConfig

    Asegúrese de reemplazar wordcount-escenario con el nombre de su aplicación puesta en escena.

    Dado que no vemos una variable de entorno de base de datos, tenemos que añadir el complemento de Postgres para el servidor de ensayo. Para ello, ejecute el siguiente comando:

    $ heroku addons:create heroku-postgresql:hobby-dev --app wordcount-stage
    Creating postgresql-cubic-86416... done, (free)
    Adding postgresql-cubic-86416 to wordcount-stage... done
    Setting DATABASE_URL and restarting wordcount-stage... done, v8
    Database has been created and is available
    ! This database is empty. If upgrading, you can transfer
    ! data from another database with pg:copy
    Use `heroku addons:docs heroku-postgresql` to view documentation.

    manía-dev es la capa gratuita del complemento Heroku Postgres.

    Ahora, cuando se corre heroku config –app wordcount-escenario de nuevo hay que ver los ajustes de conexión para la base de datos:

    === wordcount-stage Config Vars
    APP_SETTINGS: config.StagingConfig
    DATABASE_URL: postgres://azrqiefezenfrg:Zti5fjSyeyFgoc-U-yXnPrXHQv@ec2-54-225-151-64.compute-1.amazonaws.com:5432/d2kio2ubc804p7

    siguiente que necesitamos para confirmar los cambios que ha realizado en Git y empuje para el servidor de transición:

    $ git push stage master

    Ejecutar las migraciones que hemos creado para migrar nuestra base de datos provisional mediante el comando de ejecución heroku:

    $ heroku run python manage.py db upgrade --app wordcount-stage
    Running python manage.py db upgrade on wordcount-stage... up, run.5677
    INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
    INFO [alembic.runtime.migration] Will assume transactional DDL.
    INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message

    Aviso la forma en que sólo salía de la actualización, no es el init o comandos migran como antes. Ya hemos establecido nuestro archivo de migración y listo para funcionar; sólo tenemos que aplicarlo contra la base de datos Heroku.

    Vamos ahora a hacer lo mismo para la producción.

    Ahora, tanto nuestros sitios de ensayo y producción han establecido sus bases de datos y se migran – y listo para ir!

    Cuando se aplica una nueva migración de la base de datos de producción, no podría ser el tiempo de inactividad. Si esto es un problema, puede configurar la replicación de bases de datos mediante la adición de un “seguidor” (comúnmente conocido como esclavo) de base de datos. Para más información sobre esto, echa un vistazo a la documentación oficial Heroku.

    Conclusión

    Eso es todo por parte 2. Si desea profundizar en el frasco, visita nuestra serie de videos que acompaña: Bonus

    gratuito: Haga clic aquí para obtener acceso a un vídeo gratuito + Frasco Python tutorial que le muestra cómo construir aplicación web Frasco, paso a paso.

    En la parte 3 vamos a construir la funcionalidad de conteo de palabras y lo han enviado a una cola de tareas para tratar con el procesamiento de recuento de palabras ya en funcionamiento.

    Nos vemos la próxima vez. ¡Salud!

    Esta es una pieza colaboración entre la leva Linke, co-fundador de inicio Edmonton, y la gente en el Real Python.

    Categorías
    Python

    la combinación se interpreta como un carácter de tabulación.

    Aquí es una lista de secuencias de escape que causa Python Para aplicar un significado especial en lugar de interpretar literalmente: Ejemplos

    :

    >>> print(""atb"")

    la de un literal t. En cambio

    Categorías
    Python

    Proyecto de Python para principiantes: Bitcoin Precio Notificaciones

     

    Tabla de Contenidos

    • Estimado Pythonic Santa Claus … Funciones
    • recursivas en Python
    • mantener estructuras de Estado
    • recursiva de datos en Python
    • Naive La recursividad es ingenuo
    • molestos detalles
    • Fin
    • Referencias

    reloj ahora Este tutorial tiene un curso de vídeo relacionado creado por el equipo del real Python. Mira que junto con el tutorial escrito para profundizar su comprensión: Pensando de forma recursiva en Python

    “De todas las ideas que he introducido a los niños, la recursividad se destaca como la idea de que es particularmente capaz de provocar una respuesta emocionados”

    Seymour Papert, Mindstorms

    problemas (en la vida y también en la informática) a menudo pueden parecer grande y aterrador. Pero si seguimos saltando lejos en ellos, más a menudo que no podemos romperlos en trozos más pequeños lo suficientemente trivial para resolver. Esta es la esencia de pensar de forma recursiva, y mi objetivo en este artículo es proporcionar usted, mi querido lector, con las herramientas conceptuales necesarias para abordar los problemas desde este punto de vista recursiva.

    Juntos, vamos a aprender a trabajar con la recursividad en nuestros programas de Python por el dominio de conceptos tales como funciones recursivas y estructuras de datos recursivas. También hablaremos de mantener el estado durante la recursividad y evitar el recálculo almacenamiento en caché de resultados. Esto va a ser muy divertido. ¡Adelante y hacia arriba!

    Estimado Pythonic Santa Claus …

    Soy consciente de que como compañero de Pythonistas estamos todos los adultos que consienten aquí, pero los niños parecen asimilar la belleza de la recursividad mejor. Así que vamos a no ser adultos aquí por un momento y hablar sobre cómo podemos utilizar la recursividad para ayudar a Santa Claus.

    alguna vez se preguntó cómo se entregan los regalos de Navidad? Claro que tengo, y creo que Santa Claus tiene una lista de casas que recorre. Él va a una casa, cae fuera de los presentes, se come las galletas y la leche, y se mueve a la siguiente casa en la lista. Dado que este algoritmo para la entrega de regalos se basa en una construcción de bucle explícita, se llama un algoritmo iterativo.

    El algoritmo para la presente entrega iterativo implementado en Python:

    houses = ["Eric's house", "Kenny's house", "Kyle's house", "Stan's house"]

    def deliver_presents_iteratively():
    for house in houses:
    print("Delivering presents to", house)
    >>> deliver_presents_iteratively()
    Delivering presents to Eric's house
    Delivering presents to Kenny's house
    Delivering presents to Kyle's house
    Delivering presents to Stan's house

    pero me siento para Santa. A su edad, no debería tener que entregar todos los regalos por él mismo. Propongo un algoritmo con el que se puede dividir el trabajo de entrega de regalos entre sus duendes:

    • > 1 Él es un director y puede nombrar dos elfos y dividir su trabajo entre ellos
    • = 1 Es un trabajador y tiene que ofrecer los regalos a la casa asignada a él

    Esta es la estructura típica de un algoritmo recursivo. Si el problema actual representa un caso simple, resolverlo. Si no es así, dividirlo en subproblemas y aplicar la misma estrategia a ellos.

    El algoritmo recursivo para la entrega presente implementado en Python: Funciones

    houses = ["Eric's house", "Kenny's house", "Kyle's house", "Stan's house"]

    # Each function call represents an elf doing his work
    def deliver_presents_recursively(houses):
    # Worker elf doing his work
    if len(houses) == 1:
    house = houses[0]
    print("Delivering presents to", house)

    # Manager elf doing his work
    else:
    mid = len(houses) // 2
    first_half = houses[:mid]
    second_half = houses[mid:]

    # Divides his work among two elves
    deliver_presents_recursively(first_half)
    deliver_presents_recursively(second_half)
    >>> deliver_presents_recursively(houses)
    Delivering presents to Eric's house
    Delivering presents to Kenny's house
    Delivering presents to Kyle's house
    Delivering presents to Stan's house

    recursivas en Python

    Ahora que tenemos un poco de intuición acerca de la recursividad, vamos a introducir la definición formal de una función recursiva. Una función recursiva es una función definida en términos de sí mismo a través de expresiones auto-referenciales.

    Esto significa que la función continuará llamando a sí mismo y repetir su comportamiento hasta que se cumpla alguna condición para devolver un resultado. Todas las funciones recursivas comparten una estructura común formada por dos partes: caso base y caso recursivo.

    Para demostrar esta estructura, vamos a escribir una función recursiva para calcular n !:

    descomponer el problema original en los casos más sencillos de un mismo problema. Este es el caso recursivo:

    n! = n x (n−1) x (n−2) x (n−3) ⋅⋅⋅⋅ x 3 x 2 x 1
    n! = n x (n−1)!

    A medida que el gran problema se descompone en los sucesivamente menos complejos, esos subproblemas deben eventualmente se vuelven tan simples que se pueden resolver sin una mayor subdivisión. Este es el caso base:

    n! = n x (n−1)!
    n! = n x (n−1) x (n−2)!
    n! = n x (n−1) x (n−2) x (n−3)!


    n! = n x (n−1) x (n−2) x (n−3) ⋅⋅⋅⋅ x 3!
    n! = n x (n−1) x (n−2) x (n−3) ⋅⋅⋅⋅ x 3 x 2!
    n! = n x (n−1) x (n−2) x (n−3) ⋅⋅⋅⋅ x 3 x 2 x 1!

    Aquí, 1! es nuestro caso base, y es igual a 1. Función

    recursiva para calcular n! implementado en Python:

    def factorial_recursive(n):
    # Base case: 1! = 1
    if n == 1:
    return 1

    # Recursive case: n! = n * (n-1)!
    else:
    return n * factorial_recursive(n-1)
    >>> factorial_recursive(5)
    120

    Detrás de las escenas, cada llamada recursiva agrega un marco de pila (que contiene su contexto de ejecución) a la pila de llamadas hasta llegar al caso base. A continuación, la pila empieza a relajarse, ya que cada llamada devuelve sus resultados:

    Manteniendo el estado

    Cuando se trata de las funciones recursivas, tenga en cuenta que cada llamada recursiva tiene su propio contexto de ejecución, por lo que para mantener el estado durante la recursividad tiene ya sea a:

    • Pase el estado a través de cada llamada recursiva para que el estado actual es parte del contexto de ejecución de la llamada actual
    • Mantener el estado en el ámbito global

    Una demostración debe hacer las cosas más claras. Vamos a calcular 1 + 2 + 3 + 10 ⋅⋅⋅⋅ utilizando la recursividad. El estado que tenemos que mantener es (número actual estamos añadiendo, suma acumulada hasta ahora) .

    Así es como se hace eso por roscado a través de cada llamada recursiva (es decir, pasando el actual estado actualizado para cada llamada recursiva como argumentos):

    def sum_recursive(current_number, accumulated_sum):
    # Base case
    # Return the final state
    if current_number == 11:
    return accumulated_sum

    # Recursive case
    # Thread the state through the recursive call
    else:
    return sum_recursive(current_number + 1, accumulated_sum + current_number)
    # Pass the initial state
    >>> sum_recursive(1, 0)
    55

    Así es como se mantiene el estado manteniéndolo en el ámbito global:

    # Global mutable state
    current_number = 1
    accumulated_sum = 0

    def sum_recursive():
    global current_number
    global accumulated_sum
    # Base case
    if current_number == 11:
    return accumulated_sum
    # Recursive case
    else:
    accumulated_sum = accumulated_sum + current_number
    current_number = current_number + 1
    return sum_recursive()
    >>> sum_recursive()
    55

    prefiero enhebrar el estado a través de cada llamada recursiva porque encuentro estado mutable mundial a ser malo, pero eso es una discusión para otro momento. Estructuras

    recursiva de datos en la estructura de datos de Python

    A es recursivo si puede ser definido en términos de una versión más pequeña de sí mismo. Una lista es un ejemplo de una estructura de datos recursiva. Permítanme demostrar. Suponga que tiene solamente una lista vacía a su disposición, y la única operación que se puede realizar en la misma es la siguiente:

    # Return a new list that is the result of
    # adding element to the head (i.e. front) of input_list
    def attach_head(element, input_list):
    return [element] + input_list

    Uso de la lista vacía y la operación attach_head, puede generar cualquier lista. Por ejemplo, vamos a generar [1, 46, -31, «hola»]:

    attach_head(1, # Will return [1, 46, -31, "hello"]
    attach_head(46, # Will return [46, -31, "hello"]
    attach_head(-31, # Will return [-31, "hello"]
    attach_head("hello", [])))) # Will return ["hello"]
    [1, 46, -31, 'hello']

    A partir de una lista vacía, se puede generar cualquier lista mediante la aplicación recursiva de la función attach_head, y por lo tanto la estructura de datos de lista pueden definirse de forma recursiva como:

    +---- attach_head(element, smaller list)
    list = +
    +---- empty list

    recursión también puede ser visto como composición de la función auto-referencial. Aplicamos una función a un argumento, a continuación, pasar a ese resultado en como argumento para una segunda aplicación de la misma función, y así sucesivamente. Repetidamente componer attach_head consigo mismo es el mismo que attach_head hace llamar repetidamente.

    Lista

    no es la estructura de datos única recursiva. Otros ejemplos incluyen la serie, árbol, diccionario, etc. estructuras de datos recursivas

    y funciones recursivas van juntos como el pan y la mantequilla. La estructura de la función recursiva a menudo puede ser modelada después de la definición de la estructura de datos recursiva que toma como entrada. Permítanme demostrar esto calculando la suma de todos los elementos de una lista recursiva:

    def list_sum_recursive(input_list):
    # Base case
    if input_list == []:
    return 0

    # Recursive case
    # Decompose the original problem into simpler instances of the same problem
    # by making use of the fact that the input is a recursive data structure
    # and can be defined in terms of a smaller version of itself
    else:
    head = input_list[0]
    smaller_list = input_list[1:]
    return head + list_sum_recursive(smaller_list)
    >>> list_sum_recursive([1, 2, 3])
    6

    recursividad Naive es un número

    El Fibonacci Naive fueron originalmente definida por el Fibonacci matemático italiano en el siglo XIII para modelar el crecimiento de las poblaciones de conejo. Fibonacci conjeturó que el número de pares de conejos nacidos en un año dado es igual al número de pares de conejos nacidos en cada uno de los dos años anteriores, a partir de un par de conejos en el primer año.

    para contar el número de conejos nacidos en el año enésimo, que de fi ne la relación de recurrencia:

    Fn = Fn-1 + Fn-2

    Los casos base son: escritura de

    F0 = 0 and F1 = 1

    Let una función recursiva para calcular el enésimo número de Fibonacci:

    def fibonacci_recursive(n):
    print("Calculating F", "(", n, ")", sep="", end=", ")

    # Base case
    if n == 0:
    return 0
    elif n == 1:
    return 1

    # Recursive case
    else:
    return fibonacci_recursive(n-1) + fibonacci_recursive(n-2)
    >>> fibonacci_recursive(5)
    Calculating F(5), Calculating F(4), Calculating F(3), Calculating F(2), Calculating F(1),
    Calculating F(0), Calculating F(1), Calculating F(2), Calculating F(1), Calculating F(0),
    Calculating F(3), Calculating F(2), Calculating F(1), Calculating F(0), Calculating F(1),

    5

    Ingenuamente después de la recursivas definición del enésimo número de Fibonacci era bastante ineficiente. Como se puede ver en la salida anterior, estamos recalcular los valores innecesariamente. Vamos a tratar de mejorar fibonacci_recursive almacenamiento en caché de los resultados de cada cálculo de Fibonacci Fk:

    from functools import lru_cache

    @lru_cache(maxsize=None)
    def fibonacci_recursive(n):
    print("Calculating F", "(", n, ")", sep="", end=", ")

    # Base case
    if n == 0:
    return 0
    elif n == 1:
    return 1

    # Recursive case
    else:
    return fibonacci_recursive(n-1) + fibonacci_recursive(n-2)
    >>> fibonacci_recursive(5)
    Calculating F(5), Calculating F(4), Calculating F(3), Calculating F(2), Calculating F(1), Calculating F(0),

    5

    lru_cache es un decorador que almacena en caché los resultados. De esta manera, evitamos recálculo comprobando de forma explícita por el valor antes de intentar calcularlo. Una cosa a tener en cuenta sobre lru_cache es que ya que utiliza un diccionario para resultados de caché, los argumentos posicionales y de palabras clave (que sirven como claves en ese diccionario) a la función debe ser hashable.

    molestos detalles

    Python no tiene soporte para la eliminación de llamada final. Como resultado, puede causar un desbordamiento de pila si al final el uso de marcos de pila más que la profundidad de la pila de llamadas predeterminado:

    >>> import sys
    >>> sys.getrecursionlimit()
    3000

    Tenga en cuenta esta limitación si tiene un programa que requiere la repetición de profundidad.

    Además, las estructuras de datos mutables de Python no admiten el intercambio estructural, por lo que tratarlos como estructuras de datos inmutables va a afectar negativamente a su espacio y GC (recolección de basura) la eficiencia, ya que van a terminar innecesariamente copiar una gran cantidad de objetos mutables . Por ejemplo, he utilizado este modelo para descomponer listas y recursivo sobre ellos:

    >>> input_list = [1, 2, 3]
    >>> head = input_list[0]
    >>> tail = input_list[1:]
    >>> print("head --", head)
    head -- 1
    >>> print("tail --", tail)
    tail -- [2, 3]

    lo hice para simplificar las cosas por el bien de la claridad. Tenga en cuenta que la cola se crea copiando. Recursiva haciendo que más grandes listas pueden afectar negativamente a su espacio y la eficiencia GC.

    Fin

    Una vez me preguntaron para explicar la recursividad en una entrevista. Tomé una hoja de papel y escribí favor vuelca en ambos lados. El entrevistador no tuvo la broma, pero ahora que ha leído este artículo, esperamos que pueda hacer feliz Pythoning!

    Referencias

    Mira ahora Este tutorial tiene un vídeo relacionado curso creado por el equipo del Real Python. Mira que junto con el tutorial escrito para profundizar su comprensión: Pensamiento de forma recursiva en Python

    Categorías
    Python

    Acelerar su programa de Python con la Concurrencia

     

    Tabla de Contenidos

    • básico SetupWhat que realmente está pasando aquí?
    • Lo que realmente está pasando aquí? de
    • deje correr las cosas en paralelo
    • Una cuestión importante a considerar
    • Embalaje para arriba de
    • Lo que realmente está pasando aquí?

    Bienvenido!

    los artículos de esta serie:

      Parte

    • 1: Pruebas asíncrono con Django y PyVows (artículo actual)
    • Parte 2: Pruebas unitarias con pyVows y Django
    • Parte 3: Las pruebas de integración con pyVows y Django

    repo: TDD-Django

    PyVows es un puerto del desarrollo votos populares comportamiento impulsado (o BDD) marco para Node.js. Para este artículo me centraré en el uso de PyVows y selenio para ejecutar las pruebas de interfaz gráfica de usuario contra Django, y en el siguiente artículo de esta serie, voy a hablar de las pruebas unitarias con PyVows.

    Antes de empezar, tómese un minuto para leer este artículo que describe las diferencias entre el comportamiento impulsado y desarrollo basado en pruebas. El trabajo de instalación de

    básico

    Vamos a través de un conjunto de ejemplos. Iniciar un nuevo proyecto de Django (con virtualenvwrapper, django-pyVows y selenio):

    $ mkvirtualenv TDD-Django --no-site-packages
    $ workon TDD-Django
    $ pip install pyVows django django-pyVows selenium lxml cssselect
    $ django-admin.py startproject tddapp

    Esta configuración es todo lo que necesitamos por ahora. Vamos a crear nuestra primera prueba GUI con pyVows añadiendo uitests.py a tddapp, y luego añadir el siguiente código:

    from pyvows import Vows, expect
    from django_pyvows.context import DjangoHTTPContext
    from selenium import webdriver

    @Vows.batch
    class TDDDjangoApp(DjangoHTTPContext):

    def get_settings(self):
    return "tddapp.settings"

    def topic(self):
    self.start_server()
    browser = webdriver.Firefox()
    browser.get(self.get_url("/"))
    return browser

    def should_prompt_the_user_with_a_login_page(self, topic):
    expect(topic.title).to_include('Django')

    Lo que realmente está pasando aquí?

    el inicio de las importaciones de prueba todas las bibliotecas necesarias, como pyvows, django_pyvows y selenio:

    from pyvows import Vows, expect
    from django_pyvows.context import DjangoHTTPContext
    from selenium import webdriver

    La siguiente línea crea lo que en pyVows que se conoce como un lote de prueba. Un lote de prueba en pyVows se identifica por el decorador @ Vows.batch y es sinónimo de unittest.TestCase en el módulo de prueba de unidad de la biblioteca estándar de Python.

    lotes de prueba

    son contextos que describen diferentes componentes y estados que desea probar. En general, un lote de prueba heredará del Vows.Context pero en nuestro caso estamos heredando de DjangoHTTPContext como esa clase proporciona toda la funcionalidad del ayudante al horno en django_pyvows. Además de la herencia de DjangoHTTPContext necesita sobrescribir los get_settings función () y devolver la ruta de acceso al archivo de settings.py que desea utilizar para ejecutar las pruebas:

    @Vows.batch
    class TDDDjangoApp(DjangoHTTPContext):

    def get_settings(self):
    return "tddapp.settings"

    Cada contexto debe contener un solo tema, que es el el objeto que desee prueba y un número de votos que realizan las pruebas en contra de dicho tema. Para nuestro tema empezamos el servidor Django usando la función auxiliar start_server (), el fuego de selenio y selenio punto a la raíz de nuestra aplicación Django. Entonces, ya que esta es una prueba de interfaz gráfica de usuario, nuestro tema devuelve el WebDriver selenio para que podamos ejecutar nuestras pruebas.

    Nota: self.get_url ( «/») traduce la dirección URL relativa a la URL absoluta que necesitamos para acceder al sitio.

    A continuación, nuestros primeros cheques voto / prueba para ver si el título de la página incluye ‘Django’:

    def topic(self):
    self.start_server()
    browser = webdriver.Firefox()
    browser.get(self.get_url("/"))
    return browser

    def should_prompt_the_user_with_a_django_page(self, topic):
    expect(topic.title).to_include('Django')

    Ejecución de la prueba en este punto debe pasar, porque la página por defecto en Django tiene un título de “Bienvenido a Django” . Esto verifica que nuestra configuración básica es correcta y podemos seguir adelante y empezar a programar algo. La salida de la ejecución de la prueba es el siguiente: la atención

    $ pyVows -vvv uitests.py

    ============
    Vows Results
    ============

    Tdd django app
    ✓ should prompt the user with a django page
    ✓ OK » 1 honored • 0 broken (2.489381s)

    And a failed test would look like this:

    $ pyVows -vvv uitests.py

    ============
    Vows Results
    ============

    Tdd django app
    ✗ should prompt the user with a django page
    Expected topic(u'Page Not Found') to include 'Login'

    ...snipping Traceback to save space...

    ✗ OK » 0 honored • 1 broken (2.489381s)

    atención a la denominación de las pruebas en el informe. La línea indentada más exterior es el contexto (TDDDjangoApp), con cada voto / test en ese contexto que aparece y debajo de sangría. Esto hace que la presentación de informes y la búsqueda de defectos muy fácil, ya que se lee como una serie de requisitos. Considere el siguiente informe:

    $ pyVows -vvv uitests.py

    ============
    Vows Results
    ============

    Tdd django app
    on Chrome
    ✓ should prompt the user with a django page
    on Firefox
    ✗ should prompt the user with a django page

    ...snipping Traceback to save space...

    ✗ OK » 1 honored • 1 broken (3.119354s)

    En el ejemplo ficticio anterior, podemos ver que nuestra configuración está funcionando forChrome y no en Firefox. Así, mediante el uso de nombres intuitiva de las pruebas, pyVowsproduces un informe simple pero altamente eficaz para la localización de problemas. de

    deje correr las cosas en paralelo

    Además se están acercando a la prueba paralela asíncrona en varios navegadores! Vamos a echar un vistazo al código de la prueba que se habría producido ese informe:

    @Vows.batch
    class TDDDjangoApp(DjangoContext):

    class OnFirefox(DjangoHTTPContext):

    def get_settings(self):
    return "tddapp.settings"

    def topic(self):
    self.start_server(port=8888)
    browser = webdriver.Firefox()
    browser.get(self.get_url("/"))
    return browser

    def should_prompt_the_user_with_a_django_page(self, topic):
    expect(topic.title).to_include('string not in the title')

    class OnChrome(DjangoHTTPContext):

    def get_settings(self):
    return "tddapp.settings"

    def topic(self):
    self.start_server(port=8887)
    browser = webdriver.Chrome()
    browser.get(self.get_url("/"))
    return browser

    def should_prompt_the_user_with_a_django_page(self, topic):
    expect(topic.title).to_include('Django')

    En pyVows, hermanos contextos son ejecutados en contextos paralelos y anidadas se ejecutan de forma secuencial – lo que significa TDDDjangoApp sería ejecutado primero, y luego sus dos contextos anidados OnFirefox y OnChrome serían ejecutados en paralelo (porque son hermanos de la otra). sin embargo, podemos eliminar una gran parte del código duplicado mediante la creación de un conjunto estándar de pruebas y ejecutar esas pruebas contra múltiples contextos. La programación funcional

    def onBrowser(webdriver, port):
    class BrowserTests(DjangoHTTPContext):

    def get_settings(self):
    return "tddapp.settings"

    def topic(self):
    self.start_server(port=port)
    browser = webdriver()
    browser.get(self.get_url("/"))
    return browser

    def should_prompt_the_user_with_a_django_page(self, topic):
    expect(topic.title).to_include('Django')

    return BrowserTests

    @Vows.batch
    class TDDDjangoApp(DjangoContext):

    class OnChrome(onBrowser(webdriver.Chrome, 8887)):
    pass

    class OnFirefox(onBrowser(webdriver.Firefox, 8888)):
    pass

    class OnPhantonJS(onBrowser(webdriver.PhantomJS, 8886)):
    pass

    al rescate! (Bueno, algo así …) Una de las ventajas de Python es que no estará sujeto a un paradigma de programación en particular. Así que podemos usar una variedad de soluciones. En este caso, queremos crear dinámicamente un contexto de prueba para cada navegador y el puerto que queremos ejecutar las pruebas en contra.

    Para hacer esto podemos escribir todas nuestras pruebas una vez (en la clase BrowserTests, que se devuelve por la función OnBrowser). Lo bueno de esta técnica es que la función tema () en las declaraciones de clase BrowserTests cualquier WebDriver (también conocido como navegador) que se pasa a la función onBrowser.

    Desde aquí nuestro lote de prueba (denotado por @ Vows.batch) es simplemente describiendo lo que será RAN / informó. La salida de los cuales sería el siguiente:

    ============
    Vows Results
    ============

    Tdd django app
    On phantom js
    ✓ should prompt the user with a django page
    On chrome
    ✓ should prompt the user with a django page
    On firefox
    ✓ should prompt the user with a django page
    ✓ OK » 3 honored • 0 broken (4.068020s)

    Con esta configuración cada prueba añadimos a la clase BrowserTests se ejecutará againsteach navegador especificamos. Por ejemplo, si añadimos las siguientes pruebas para la clase theBrowserTests …

    def heading_should_tell_the_user_it_worked(self,topic):
    heading_text = topic.find_element_by_css_selector("#summary h1").text
    expect(heading_text).to_equal("It worked!")

    def should_display_debug_message(self,topic):
    explain_text = topic.find_element_by_id("explanation").text
    expect(explain_text).to_include("DEBUG = True")

    … entonces el informe mostraría:

    ============
    Vows Results
    ============

    Tdd django app
    On firefox
    ✓ should prompt the user with a django page
    ✓ heading should tell the user it worked
    ✓ should display debug message
    On chrome
    ✓ heading should tell the user it worked
    ✓ should prompt the user with a django page
    ✓ should display debug message
    On phantom js
    ✓ should prompt the user with a django page
    ✓ should display debug message
    ✓ heading should tell the user it worked
    ✓ OK » 9 honored • 0 broken (4.238522s)

    Una cuestión importante a considerar

    Usted puede preguntarse por qué, sin embargo, estamos llamando start_server por cada nuevo contexto. En realidad no tenemos que hacer esto, pero estamos trabajando en torno a una limitación de django_pyvows. Desafortunadamente la función DjangoHTTPContext.start_server () crea un solo hilo, lo que disminuye el rendimiento. Para este conjunto de pruebas, por ejemplo, tiempo de ejecución aumenta desde unos 5 segundos (lo escrito anteriormente) a aproximadamente 21 segundos si sólo crean un servidor CherryPy.

    Lo ideal sería que desee crear un solo servidor de prueba en contra y perhapsmake el servidor multi-hilo, de modo que no tenemos que incurrir en el performancepenalty. Así que vamos a ver si podemos hacer que eso ocurra. En primer lugar la actualización del código Let TheTest utilizar pyVows noción de contexto herencia tan sólo tenemos que createthe servidor una vez.

    def onBrowser(webdriver):
    class BrowserTests(DjangoHTTPContext):

    def topic(self):
    browser = webdriver()
    browser.get(self.get_url("/"))
    return browser

    def should_prompt_the_user_with_a_login_page(self, topic):
    expect(topic.title).to_include('Django')

    return BrowserTests

    @Vows.batch
    class TDDDjangoApp(DjangoHTTPContext):

    def get_settings(self):
    return "tddapp.settings"

    def topic(self):
    self.start_server()

    class OnChrome(onBrowser(webdriver.Chrome)):
    pass

    class OnFirefox(onBrowser(webdriver.Firefox)):
    pass

    class OnPhantonJS(onBrowser(webdriver.PhantomJS)):
    pass

    Aviso cómo el contexto TDDDjangoApp ahora llama start_server () de su topicfunction y ya no hay necesidad de pasar de un puerto a nuestra función contextcreation onBrowser (). Ahora tenemos una única versión del servidor de instantiate theCherryPy y ejecutar todas las pruebas en contra de eso. Esto tiene la ventaja de utilizar menos resourcesand hace que el código sea más fácil de mantener.

    para lidiar con el problema de rendimiento, que puede manejar manualmente los hilos para obtener pruebas que se ejecutan más rápido:

    def onBrowser(webdriver):
    class BrowserTests(DjangoHTTPContext):

    def topic(self):
    webdriver.get(self.get_url("/"))
    return webdriver

    def teardown(self):
    webdriver.quit()

    def should_prompt_the_user_with_a_login_page(self, topic):
    expect(topic.title).to_include('Django')

    return BrowserTests

    @Vows.batch
    class TDDDjangoApp(DjangoHTTPContext):

    def get_settings(self):
    return "tddapp.settings"

    def topic(self):
    self.start_server()
    #manual add some more threads to the CherryPy server
    self.server.thr.server.requests.grow(3)

    def teardown(self):
    #clean up the threads so we can exit cleanly
    self.server.thr.server.requests.stop(timeout=1)

    class OnChrome(onBrowser(webdriver.Chrome())):
    pass

    class OnFirefox(onBrowser(webdriver.Firefox())):
    pass

    class OnPhantonJS(onBrowser(webdriver.PhantomJS())):
    pass

    Hemos hecho tres cosas aquí. En primer lugar, en la función de tema () hemos añadido tres morethreads a grupo de subprocesos de CherryPy:

    def topic(self):
    self.start_server()
    #manual add some more threads to the CherryPy server
    self.server.thr.server.requests.grow(3)

    En segundo lugar, era necesario asegurarse de que los hilos se limpiaron o la prueba de runwill nunca es completa.

    def teardown(self):
    #clean up the threads so we can exit cleanly
    self.server.thr.server.requests.stop(timeout=1)

    Por último, aseguró que WebDriver limpia después de sí mismo mediante la adición de una función de desmontaje a nuestra clase BrowserTest:

    def teardown(self):
    webdriver.quit()

    Embalaje para arriba de

    nodo no es el único juego en la ciudad que se pueden hacer las cosas de forma asíncrona. Y con el puerto de Vows.js a pyVows y un poco de ingenio podemos obtener pruebas en paralelo con varios navegadores para Django en marcha con muy poco esfuerzo.

    Teniendo esto un paso más allá, que podría vincularse a algo así como BrowserMob o SauceLabs a prueba contra un gran número de navegadores y entonces las cosas sería realmente comenzar a ponerse interesante. Además, con sencillo, fácil de entender que informa y una sintaxis muy limpia, sus pruebas de interfaz gráfica de usuario puede llegar a ser (relativamente) indoloro y rápido!

    El código utilizado para este artículo se puede encontrar en el repositorio de Github asociado.

    me dejó saber lo que piensa en los comentarios a continuación. ¡Salud!

    Categorías
    Python

    Desarrollo Python en código de Visual Studio (Guía de instalación)

     

    Tabla de Contenidos

    • Bitcoin Precio Notificaciones con la configuración del proyecto Python
    • Recuperando el Bitcoin Precio
    • El envío de una notificación de prueba IFTTT
    • Creación IFTTT applets
    • Poniendo todo junto
    • Resumen y próximos pasos

    Bienvenidos al primer artículo de una serie de artículos sobre los proyectos de Python para principiantes!

    En este tutorial vamos a construir una notificación precio Bitcoin servicio-

    Durante este proyecto usted aprenderá acerca de las peticiones HTTP y cómo enviar usando el paquete (nombre apropiado) solicita.

    Vas a aprender sobre WebHooks y cómo se puede utilizar para conectar su aplicación Python para servicios externos, como las notificaciones telefónicas o mensajes de telegrama.

    con relativamente poco de código (~ 50 líneas) que van a llegar a un servicio de notificación de pleno derecho precio Bitcoin que será fácilmente ampliable a otros cryptocurrencies y servicios.

    Así que vamos a saltar a la derecha:

    Bitcoin Precio Notificaciones Con Python

    Como todos sabemos, el precio de Bitcoin es una cosa caprichosa. Nunca se sabe donde va a ser al final del día. Así, en lugar de comprobar constantemente diversos sitios de las últimas actualizaciones, vamos a hacer una aplicación Python para hacer el trabajo para usted.

    Para ello, vamos a utilizar el popular sitio web IFTTT automatización. IFTTT ( “si esto, entonces eso”) es un servicio web que sirve de puente entre diferentes aplicaciones y dispositivos.

    Vamos a crear dos subprogramas: ifttt

    • uno para notificación de emergencia cuando el precio de Bitcoin cae por debajo de cierto umbral; y
    • otro para actualizaciones regulares del telegrama en el precio de Bitcoin.

    Ambos serán provocada por nuestra aplicación Python que consumirá los datos de la API Coinmarketcap.

    Un IFTTT applet se compone de dos partes: un gatillo y una acción.

    En nuestro caso, el gatillo será un servicio web hook proporcionada por IFTTT. Se puede pensar en WebHooks como “devoluciones de llamada HTTP definidos por el usuario” y puede leer más aboutthem aquí.

    Nuestra Python aplicación va a hacer una petición HTTP a la URL web hook que desencadenará una acción. Ahora bien, esta es la parte divertida de la acción podría ser casi cualquier cosa que desee. IFTTT ofrece una multitud de acciones como el envío de un correo electrónico, la actualización de una hoja de cálculo de Google e incluso llamando a su teléfono. Configuración de inicio

    Proyecto

    Let mediante la creación de un environment.Run virtual de este comando para obtener un nuevo Python 3 entorno virtual:

    $ mkvirtualenv -p $(which python3) bitcoin_notifications

    Antes de continuar hay que activar el entorno virtual e instalar las dependencias necesarias:

    $ workon bitcoin_notifications # To activate the virtual environment
    $ pip install requests==2.18.4 # We only need the requests package

    Puede desactivar el entorno virtual mediante la ejecución del comando de desactivación shell.

    Recuperando el precio Bitcoin

    hora de poner las manos sucias. Podemos empezar por conseguir el último precio de la API Coinmarketcap en la consola de Python:

    En primer lugar, tenemos que importar el módulo de peticiones y definir la variable bitcoin_api_url que contiene la API URL Coinmarketcap de Bitcoin.

    A continuación, se envía una petición HTTP GET a la URL utilizando la función requests.get () y guardar la respuesta. Dado que la API devuelve una respuesta JSON, podemos convertirlo en un objeto de Python llamando a la función .json () sobre la respuesta. Como se puede ver, la API devuelve una lista con un elemento que contiene los datos de precios Bitcoin:

    >>> import requests
    >>> bitcoin_api_url = 'https://api.coinmarketcap.com/v1icker/bitcoin/'
    >>> response = requests.get(bitcoin_api_url)
    >>> response_json = response.json()
    >>> type(response_json) # The API returns a list

    >>> # Bitcoin data is the first element of the list
    >>> response_json[0]
    {'id': 'bitcoin', 'name': 'Bitcoin', 'symbol': 'BTC', 'rank': '1',
    'price_usd': '10226.7', 'price_btc': '1.0', '24h_volume_usd': '7585280000.0',
    'market_cap_usd': '172661078165', 'available_supply': '16883362.0',
    'total_supply': '16883362.0', 'max_supply': '21000000.0',
    'percent_change_1h': '0.67', 'percent_change_24h': '0.78',
    'percent_change_7d': '-4.79', 'last_updated': '1519465767'}

    La propiedad que estamos en el más interesado es ‘price_usd’-precio Bitcoin en dólares estadounidenses.

    El envío de una notificación de prueba IFTTT

    Ahora podemos pasar al lado IFTTT de las cosas. Para utilizar IFTTT primero tendrá que configurar una nueva cuenta e instalar su aplicación móvil (si desea recibir notificaciones telefónicas de su aplicación Python). Una vez que poner esto en marcha, vamos a crear un nuevo applet IFTTT para propósitos de prueba.

    Para crear una nueva prueba del applet siga estos pasos:

    Para ver la documentación sobre cómo utilizar el IFTTT WebHooks ir a esta página y hacer clic en el botón “Documentación” en la esquina superior derecha. La página de documentación contiene la dirección URL web hook y se ve así:

    https://maker.ifttt.comrigger/{event}/with/key/{your-IFTTT-key}

    El siguiente, tendrá que sustituir el evento {} parte con el nombre que le dio a nuestro evento en el paso 3, cuando se creó el applet. El {su-IFTTT-key} parte ya contiene su clave IFTTT.

    Ahora copiar la URL web hook y empezar otra consola Python. Una vez más importamos módulo de las solicitudes y definimos la variable URL web hook. Ahora sólo tenemos que enviar una solicitud HTTP POST a la URL IFTTT web hook utilizando la función requests.post ():

    >>> import requests
    >>> # Make sure that your key is in the URL
    >>> ifttt_webhook_url = 'https://maker.ifttt.comriggerest_event/with/key/{your-IFTTT-key}'
    >>> requests.post(ifttt_webhook_url)

    Después de ejecutar la última línea debería ver una notificación en su teléfono:

    Creación de applets IFTTT

    Ahora finalmente estamos listos para la parte principal. Antes de comenzar con el código que necesitamos para crear dos nuevos applets ifttt: uno para las notificaciones Bitcoinprice de emergencia y uno para recibir actualizaciones periódicas.

    emergencia bitcoin applet de notificación de precio:

    actualizaciones periódicas de los precios del applet:

    Nota: Al crear este applet se tendrá que autorizar el bot IFTTT telegrama.

    Poniendo todo junto

    Ahora que tenemos IFTTT fuera del camino, vamos a empezar a programar! Vamos a empezar por la creación de la línea de comandos de Python-esqueleto de aplicación estándar que se muestra a continuación. Tome este código y guardarlo en un archivo llamado bitcoin_notifications.py:

    import requests
    import time
    from datetime import datetime

    def main():
    pass

    if __name__ == '__main__':
    main()

    A continuación, tenemos que traducir las dos sesiones de consola Python anteriores en dos funciones que devolverán el último precio de Bitcoin y post a la IFTTT web hook respectivamente. Añadir las siguientes funciones por encima de la función principal:

    BITCOIN_API_URL = 'https://api.coinmarketcap.com/v1icker/bitcoin/'
    IFTTT_WEBHOOKS_URL = 'https://maker.ifttt.comrigger/{}/with/key/{your-IFTTT-key}'

    def get_latest_bitcoin_price():
    response = requests.get(BITCOIN_API_URL)
    response_json = response.json()
    # Convert the price to a floating point number
    return float(response_json[0]['price_usd'])

    def post_ifttt_webhook(event, value):
    # The payload that will be sent to IFTTT service
    data = {'value1': value}
    # inserts our desired event
    ifttt_event_url = IFTTT_WEBHOOKS_URL.format(event)
    # Sends a HTTP POST request to the webhook URL
    requests.post(ifttt_event_url, json=data)

    El get_latest_bitcoin_price es más o menos el mismo, a excepción de la parte en la que tenemos que convertir el precio de una cadena en un número de coma flotante. El post_ifttt_webhook toma en dos parámetros: evento y valor. El

    corresponde parámetro de evento al que sea el nombre del evento que dio a nuestro gatillo al configurar el applet IFTTT. Además, los WebHooks ifttt nos permiten enviar datos adicionales junto con la solicitud como datos con formato JSON.

    Es por eso que necesitamos el parámetro de valor: Cuando la creación de applets que dejó una etiqueta {{}} Valor1 en nuestros campos del mensaje. Esta etiqueta se sustituye por el texto ‘valor1’ de la carga útil JSON. La función requests.post () nos permite enviar datos JSON adicionales simplemente añadiendo la palabra clave JSON.

    Ahora podemos pasar a la base de nuestra aplicación en la función principal. Estará formado por un bucle Es cierto tiempo desde que queremos que nuestra aplicación se ejecute siempre. En el loopwe va a llamar a la API Coinmarketcap a conseguir el último precio de Bitcoin y registrar la fecha y hora actuales.

    basado en el precio actual que decidirá si queremos enviar una notificación de emergencia. Para nuestras actualizaciones regulares del telegrama también vamos a añadir el precio y la fecha actual a una lista bitcoin_history. Una vez que la lista llega a un cierto número de elementos (por ejemplo 5) vamos a dar formato a los elementos, enviar la actualización a Telegram, y restaurar el historial de actualizaciones futuras.

    Wheew! Como se puede ver, hay mucho que hacer en esta aplicación. Si usted está teniendo problemas para seguir el código que tenemos hasta el momento y luego tomar un pequeño descanso y volver a leer la sección anterior de nuevo lentamente. Este material no es fácil, así que tome su tiempo y no se preocupe por conseguir todo perfecto la primera vez.

    Una cosa importante es evitar el envío de estas solicitudes con demasiada frecuencia, por dos razones:

    • los estados API Coinmarketcap que actualicen los datos sólo una vez cada 5 minutos, por lo que no hay punto de volver a cargar la información más reciente de fijación de precios con mayor frecuencia que que
    • si su aplicación envía demasiadas peticiones a la API Coinmarketcap su IP podría obtener prohibido o suspendido temporalmente.

    Eso es por qué tenemos que “ir a dormir” (detener la ejecución del bucle) durante al menos 5 minutos antes de que tengamos nuevos datos. El código siguiente implementa todas las funciones requeridas he dicho anteriormente:

    BITCOIN_PRICE_THRESHOLD = 10000 # Set this to whatever you like

    def main():
    bitcoin_history = []
    while True:
    price = get_latest_bitcoin_price()
    date = datetime.now()
    bitcoin_history.append({'date': date, 'price': price})

    # Send an emergency notification
    if price < BITCOIN_PRICE_THRESHOLD: post_ifttt_webhook('bitcoin_price_emergency', price) # Send a Telegram notification # Once we have 5 items in our bitcoin_history send an update if len(bitcoin_history) == 5: post_ifttt_webhook('bitcoin_price_update', format_bitcoin_history(bitcoin_history)) # Reset the history bitcoin_history = [] # Sleep for 5 minutes # (For testing purposes you can set it to a lower number) time.sleep(5 * 60)

    Ya casi hemos terminado! Lo único que falta es la función format_bitcoin_history. Toma el bitcoin_history como un argumentand formatos que utilizan algunas de las etiquetas HTML básicas permitidas por telegrama, al igual que
    , , , y así sucesivamente. Copia este functionabove la función principal:

    def format_bitcoin_history(bitcoin_history):
    rows = []
    for bitcoin_price in bitcoin_history:
    # Formats the date into a string: '24.02.2018 15:09'
    date = bitcoin_price['date'].strftime('%d.%m.%Y %H:%M')
    price = bitcoin_price['price']
    # (bold) tag creates bolded text
    # 24.02.2018 15:09: $10123.4
    row = '{}: ${}'.format(date, price)
    rows.append(row)

    # Use a
    (break) tag to create a new line
    # Join the rows delimited by
    tag: row1
    row2
    row3
    return '
    '.join(rows)

    Esto es lo que el resultado final debe ser similar en su teléfono:

    Para ejecutar la aplicación de notificación de precios, ejecute lo siguiente en su terminal de línea de comandos:

    $ python bitcoin_notifications.py

    eso es todo ! En poco más de 50 líneas de código Python, que ha creado su propio servicio de notificación de Bitcoin. ¡Felicidades! A continuación he addedthe código entero así que usted puede comparar y ver si te has perdido nada:

    Solución

    : Pitón Bitcoin Precio notificador Mostrar / Ocultar

    import requests
    import time
    from datetime import datetime

    BITCOIN_PRICE_THRESHOLD = 10000
    BITCOIN_API_URL = 'https://api.coinmarketcap.com/v1icker/bitcoin/'
    IFTTT_WEBHOOKS_URL = 'https://maker.ifttt.comrigger/{}/with/key/{your-IFTTT-key}'

    def get_latest_bitcoin_price():
    response = requests.get(BITCOIN_API_URL)
    response_json = response.json()
    return float(response_json[0]['price_usd']) # Convert the price to a floating point number

    def post_ifttt_webhook(event, value):
    data = {'value1': value} # The payload that will be sent to IFTTT service
    ifttt_event_url = IFTTT_WEBHOOKS_URL.format(event) # Inserts our desired event
    requests.post(ifttt_event_url, json=data) # Sends a HTTP POST request to the webhook URL

    def format_bitcoin_history(bitcoin_history):
    rows = []
    for bitcoin_price in bitcoin_history:
    date = bitcoin_price['date'].strftime('%d.%m.%Y %H:%M') # Formats the date into a string: '24.02.2018 15:09'
    price = bitcoin_price['price']
    # (bold) tag creates bolded text
    row = '{}: ${}'.format(date, price) # 24.02.2018 15:09: $10123.4
    rows.append(row)

    # Use a
    (break) tag to create a new line
    return '
    '.join(rows) # Join the rows delimited by
    tag: row1
    row2
    row3

    def main():
    bitcoin_history = []
    while True:
    price = get_latest_bitcoin_price()
    date = datetime.now()
    bitcoin_history.append({'date': date, 'price': price})

    # Send an emergency notification
    if price < BITCOIN_PRICE_THRESHOLD: post_ifttt_webhook('bitcoin_price_emergency', price) # Send a Telegram notification if len(bitcoin_history) == 5: # Once we have 5 items in our bitcoin_history send an update post_ifttt_webhook('bitcoin_price_update', format_bitcoin_history(bitcoin_history)) # Reset the history bitcoin_history = [] time.sleep(5 * 60) # Sleep for 5 minutes (for testing purposes you can set it to a lower number) if __name__ == '__main__': main()

    Resumen y próximos pasos

    En este artículo, hemos creado nuestro propio Bitcoin servicio de notificación. Ha aprendido a enviar HTTP GET y POST peticiones utilizando el paquete de solicitudes. Ya viste lo fácil que era para conectar su aplicación Python para servicios externos utilizando IFTTT y WebHooks.

    Ahora, ¿dónde debe ir ahora? Con Python y IFTTT el cielo es el límite. Pero aquí hay algunas sugerencias que pueden ayudarle a empezar: las hojas de cálculo

    • igual? Utilice una acción IFTTT que agregará los precios Bitcoin a una hoja de cálculo de Google
    • Mejorar la condición de precio
    • Como Etereum / litecoin / dogecoin mejor? Cambiar el get_latest_bitcoin_price a get_latest_cryptocurrency_price que tendrá un criptomoneda como parámetro y devolver su precio
    • Usted quiere que el precio en una moneda diferente? Compruebe la API Coinmarketcap para el parámetro de conversión.

    Además, esta será una serie en curso con más proyectos de Python se puede construir a crecer sus habilidades. No se pierda en el siguiente tutorial:

    Informarte: no se pierda el seguimiento a este tutorial-Clic aquí para unirse al Boletín pitón real y sabrá cuando la próxima entrega sale.

    Buena suerte y feliz Pythoning! Déjame saber lo que se ha construido utilizando Python y IFTTT en los comentarios!

    Categorías
    Python

    Los operadores y expresiones en Python

     

    Tabla de Contenidos

    • Fetching DataThe guión
    • El guión
    • Visualización
    • BowerUpdate index.html
    • actualización index.html
    • D3SetupMain ConfigBubble ConfigSVG ConfigRequest la instalación de DataTooltipsRefactorCSS
    • configuración principal
    • burbuja Config
    • SVG Config
    • solicitar los datos
    • OceanDeploy sobre herramientas
    • Refactor
    • CSS
    • DeployingSetup digital ConfigUpdate app.py:Deploy! Configuración
    • Digital Océano
    • Implementar Config
    • actualización app.py:
    • Implementar!
    • próximos pasos
    • El guión
    • actualización index.html Configuración
    • configuración principal
    • burbuja Config
    • SVG Config
    • solicitar los datos sobre herramientas
    • Refactor
    • CSS
    • Configuración

    • digital Océano
    • Implementar Config
    • actualización app.py:
    • Implementar!

    En este tutorial vamos a construir una aplicación web a los datos de agarre desde el NASDAQ-100 y visualizar como un gráfico de burbujas con D3. Luego, para colmo, vamos a implementar esta en Ocean Digital a través de Dokku.

    Nota: Los gráficos de burbujas son perfectos para la visualización de cientos de valores en un espacio pequeño. Sin embargo, son más difíciles de leer debido a que puede ser difícil diferenciar los círculos de tamaño similar. Si está trabajando con sólo unos pocos valores, un gráfico de barras es probablemente la mejor opción ya que es mucho más fácil de leer.

    principales herramientas utilizadas en este tutorial: v2.7.8 Python, v0.10.1 Frasco, las solicitudes v2.4.1, v3.4.11 D3, Dokku v0.2.3 y v1.3.9 Bower

    Empiece por localizar y descargar el archivo _app_boilerplate .zip de este repositorio. Este archivo contiene un frasco repetitivo. Una vez descargado, extraer el archivo y carpetas, active un virtualenv, e instalar las dependencias con Pip:

    pip install -r requirements.txt

    Entonces prueba para asegurarse de que funciona: Fuego hasta el servidor, abra su navegador y vaya a http: // localhost: 5000 /. Debería ver “Hola, mundo!” mirando atrás a usted.

    Recogida de Datos

    Crear una nueva ruta y la función de vista en el archivo app.py :

    @app.route("/data")
    def data():
    return jsonify(get_data())

    actualización de las importaciones:

    from flask import Flask, render_template, jsonify
    from stock_scraper import get_data

    lo tanto, cuando esa ruta se llama, convierte el valor devuelto por una función llamada get_data () para JSON y luego devuelve. Esta función reside en un archivo llamado stock_scraper.py , que – sorpresa! – obtiene datos desde el NASDAQ-100.

    El guión

    Añadir stock_scraper.py al directorio principal.

    Tu turno : Crear el guión por su cuenta, siguiendo estos pasos:

    ¿Cómo te fue? ¿Necesitas ayuda? Echemos un vistazo a una posible solución: acontecimiento

    import csv
    import requests

    URL = "http://www.nasdaq.com/quotes
    asdaq-100-stocks.aspx?render=download"

    def get_data():
    r = requests.get(URL)
    data = r.text
    RESULTS = {'children': []}
    for line in csv.DictReader(data.splitlines(), skipinitialspace=True):
    RESULTS['children'].append({
    'name': line['Name'],
    'symbol': line['Symbol'],
    'symbol': line['Symbol'],
    'price': line['lastsale'],
    'net_change': line['netchange'],
    'percent_change': line['pctchange'],
    'volume': line['share_volume'],
    'value': line['Nasdaq100_points']
    })
    return RESULTS

    de qué?

    NOTA: También es posible usar una comprensión dict para crear los diccionarios individuales. Este es un método mucho más eficiente, sin embargo se sacrifica la legibilidad. Tu llamada.

    tiempo para probar: Fuego hasta el servidor y vaya a http: // localhost: 5000 / datos. Si todo va bien, debería ver un objeto que contiene los datos de saldos pertinentes.

    Con los datos en la mano, que ahora puede trabajar con visualizándolo en el front-end.

    Visualización

    Junto con HTML y CSS, que va a utilizar Bootstrap, Javascript / jQuery, y D3 al poder nuestro front-end. También utilizaremos el lado del cliente herramienta de gestión de la dependencia Bower de descargar y administrar estas bibliotecas.

    Tu turno : Siga las instrucciones de instalación para configurar Bower en su máquina. Consejo: Usted tendrá que instalar Node.js antes de instalar Bower .

    listo? Se necesitan archivos

    Bower

    dos para obtener glorieta ir – bower.json y .bowerrc .

    Este último archivo se utiliza para configurar Bower. Añadir al directorio principal:

    {
    "directory": "static/bower_components"
    }

    esto sólo indica que se desea las dependencias instaladas en el directorio bower_components (convención) dentro del directorio estática de la aplicación.

    Mientras tanto, el primer archivo, bower.json , almacena la glorieta de manifiesto – que significa que contiene metadatos sobre los componentes Bower, así como la propia aplicación. El archivo se puede crear de forma interactiva con el comando init glorieta. Hacerlo ahora. Basta con aceptar todos los valores predeterminados.

    Ahora, podemos instalar las dependencias.

    $ bower install bootstrap#3.2.0 jquery#2.1.1 d3#3.4.11 --save

    La bandera –save añade los paquetes a la bower.json dependencias matriz. Echale un vistazo. También, asegúrese de que las versiones de dependencia en bower.json coinciden con las versiones que especificamos – es decir, de arranque # 3.20.

    Con nuestras dependencias instaladas, vamos a hacerlos accesibles en nuestra aplicación.

    actualización index.html




    Flask Stock Visualizer<itle><br /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href={{ url_for('static', filename='./bower_components/bootstrap/dist/css/bootstrap.min.css') }} rel="stylesheet" media="screen"> <link href={{ url_for('static', filename='main.css') }} rel="stylesheet" media="screen"> </head><br /> <body></p> <div class="container"> </div> <p> <script src={{ url_for('static', filename='./bower_components/jquery/dist/jquery.min.js') }}></script><br /> <script src={{ url_for('static', filename='./bower_components/bootstrap/dist/js/bootstrap.min.js') }}></script><br /> <script src={{ url_for('static', filename='./bower_components/d3/d3.min.js') }}></script><br /> <script src={{ url_for('static', filename='main.js') }}></script><br /> </body><br /> </html><br /> </code> </p> <h2> D3 </h2> <p> con tantos marcos de visualización de datos por ahí, ¿por qué D3? Bueno, D3 es un nivel bastante bajo, por lo que vamos a construir el tipo de marco que desea. Una vez que anexar los datos a la DOM, se utiliza una combinación de CSS3, HTML5, SVG y para crear la visualización real. A continuación, puede añadir interactividad a través de transiciones incorporada basada en los datos de-D3. </p> <p> Para ser justos, esta biblioteca no es para todos. Puesto que usted tiene una gran cantidad de libertad para construir lo que quiere, la curva de aprendizaje es bastante alto. Si usted está buscando para un comienzo rápido, echa un vistazo a Python-NVD3, que es un contenedor de D3, que sirve para facilitar el trabajo con D3 mucho, mucho más fácil. No estamos utilizando todo por este tutorial sin embargo, ya Python-NVD3 no soporta gráficos de burbujas. </p> <p> <strong> Tu turno </strong>: Ir a través de la introducción D3 tutorial. </p> <p> Ahora vamos a código. Configuración </p> <h3> </h3> <p> Agregue el código siguiente para <em> main.js </em>: </p> <p> <code>// Custom JavaScript</p> <p>$(function() {<br /> console.log('jquery is working!');<br /> createGraph();<br /> });</p> <p>function createGraph() {<br /> // Code goes here<br /> }<br /> </code> </p> <p> Aquí, después de la carga de la página inicial, registramos ‘! JQuery está trabajando’ a la consola y luego se disparó una función llamada createGraph (). Prueba de esto. Pon en marcha el servidor A continuación, vaya a http: // localhost: 5000 / y con la consola JavaScript abierta, actualice la página. Debería ver el ‘jQuery está trabajando!’ Texto si todo iba bien. </p> <p> Añadir la siguiente etiqueta en el archivo index.html <em> </em>, dentro de la etiqueta </p> <div> que tiene un id de contenedor (después de la línea 10), para mantener la D3 gráfico de burbujas: </p> <p> <code></p> <div id="chart"></div> <p></code> </p> <h3> configuración principal </h3> <p> Añadir la siguiente código a la función createGraph () en <em> main.js </em>: </p> <p> <code>var width = 960; // chart width<br /> var height = 700; // chart height<br /> var format = d3.format(",d"); // convert value to integer<br /> var color = d3.scale.category20(); // create ordinal scale with 20 colors<br /> var sizeOfRadius = d3.scale.pow().domain([-100,100]).range([-50,50]); // https://github.com/mbostock/d3/wiki/Quantitative-Scales#pow<br /> </code> </p> <p> Asegúrese de consultar los comentarios de código para una explantación, así como la documentación oficial D3. Mira nada hasta que no entiende. <em> Un codificador debe ser autosuficiente! </em> </p> <h3> burbuja Config </h3> <p> <code>var bubble = d3.layout.pack()<br /> .sort(null) // disable sorting, use DOM tree traversal<br /> .size([width, height]) // chart layout size<br /> .padding(1) // padding between circles<br /> .radius(function(d) { return 20 + (sizeOfRadius(d) * 30); }); // radius for each circle<br /> </code> </p> <p> Una vez más, añadir el código anterior para la función createGraph (), y comprobar la documentación para cualquier pregunta. </p> <h3> SVG Config </h3> <p> A continuación, añadir el siguiente código a createGraph (), que selecciona el elemento con el id de la tabla, a continuación, añade los círculos junto con una serie de atributos: </p> <p> <code>var svg = d3.select("#chart").append("svg")<br /> .attr("width", width)<br /> .attr("height", height)<br /> .attr("class", "bubble");<br /> </code> </p> <p> Continuando con el createGraph () función, ahora tenemos que tomar los datos, que se pueden hacer de forma asíncrona con D3. </p> <h3> solicitar los datos </h3> <p> <code>// REQUEST THE DATA<br /> d3.json("/data", function(error, quotes) {<br /> var node = svg.selectAll('.node')<br /> .data(bubble.nodes(quotes)<br /> .filter(function(d) { return !d.children; }))<br /> .enter().append('g')<br /> .attr('class', 'node')<br /> .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'});</p> <p> node.append('circle')<br /> .attr('r', function(d) { return d.r; })<br /> .style('fill', function(d) { return color(d.symbol); });</p> <p> node.append('text')<br /> .attr("dy", ".3em")<br /> .style('text-anchor', 'middle')<br /> .text(function(d) { return d.symbol; });<br /> });<br /> </code> </p> <p> Así, nos encontramos con el punto final / datos que hemos creado antes para devolver los datos. El resto de este código simplemente añade las burbujas y el texto en el DOM. Se trata de código repetitivo estándar, modificado ligeramente para nuestros datos. </p> <h3> sobre herramientas </h3> <p> Ya que tenemos un espacio limitado en el gráfico, aún dentro de la función createGraph (), Vamos a añadir algo sobre herramientas que muestran información adicional sobre cada uno específico de valores. </p> <p> <code>// tooltip config<br /> var tooltip = d3.select("body")<br /> .append("div")<br /> .style("position", "absolute")<br /> .style("z-index", "10")<br /> .style("visibility", "hidden")<br /> .style("color", "white")<br /> .style("padding", "8px")<br /> .style("background-color", "rgba(0, 0, 0, 0.75)")<br /> .style("border-radius", "6px")<br /> .style("font", "12px sans-serif")<br /> .text("tooltip");<br /> </code> </p> <p> Estos son sólo los estilos CSS asociados con la información sobre herramientas. Todavía tenemos que añadir los datos reales. Actualizar el código donde añadimos los círculos para el DOM: </p> <p> <code>node.append("circle")<br /> .attr("r", function(d) { return d.r; })<br /> .style('fill', function(d) { return color(d.symbol); })</p> <p> .on("mouseover", function(d) {<br /> tooltip.text(d.name + ": $" + d.price);<br /> tooltip.style("visibility", "visible");<br /> })<br /> .on("mousemove", function() {<br /> return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");<br /> })<br /> .on("mouseout", function(){return tooltip.style("visibility", "hidden");});<br /> </code> </p> <p> probar esto, vaya a http: // localhost: 5000 /. Ahora, cuando Hoover sobre un círculo, verá algunos metadatos subyacente – nombre de la empresa y el precio de las acciones. </p> <p> <strong> Tu turno </strong>: Añadir más metadatos. ¿Qué otros datos cree que es relevante? Pensar en lo que estamos mostrando aquí – el cambio relativo en el precio. Usted tal vez podría calcular el precio anterior y mostrar: </p> <h3> Refactor </h3> <p> stocksWhat si sólo queríamos para visualizar las acciones con un índice de valor ponderado de mercado modificado – la columna de la NASDAQ-100 Puntos – mayor que 0,1? </p> <p> Añadir un condicional a los get_data () Función: </p> <p> <code>def get_data():<br /> r = requests.get(URL)<br /> data = r.text<br /> RESULTS = {'children': []}<br /> for line in csv.DictReader(data.splitlines(), skipinitialspace=True):<br /> if float(line['Nasdaq100_points']) > .01:<br /> RESULTS['children'].append({<br /> 'name': line['Name'],<br /> 'symbol': line['Symbol'],<br /> 'symbol': line['Symbol'],<br /> 'price': line['lastsale'],<br /> 'net_change': line['netchange'],<br /> 'percent_change': line['pctchange'],<br /> 'volume': line['share_volume'],<br /> 'value': line['Nasdaq100_points']<br /> })<br /> return RESULTS<br /> </code> </p> <p> Ahora, vamos a aumentar el radio de cada burbujas, en la sección de configuración de la burbuja <em> main.js </em>; modificar el código en consecuencia: </p> <p> <code>// Radius for each circle<br /> .radius(function(d) { return 20 + (sizeOfRadius(d) * 60); });<br /> </code> </p> <h3> CSS </h3> <p> Por último, vamos a añadir algunos estilos básicos para <em> main.css </em>: </p> <p> <code>body {<br /> padding-top: 20px;<br /> font: 12px sans-serif;<br /> font-weight: bold;<br /> }<br /> </code> </p> <p> mirada buena? Listo para implementar? </p> <h2> Implementación de </h2> <p> Dokku es un código abierto, Heroku-como, Plataforma como servicio (PaaS), alimentado por acoplable. Una vez configurado, puede llevar a su aplicación a la misma con Git. </p> <p> Estamos utilizando Océano Digital como nuestro anfitrión. Empecemos. Configuración </p> <h3> Digital Océano </h3> <p> Regístrese para obtener una cuenta, si no tiene ya uno. A continuación, siga esta guía para agregar una clave pública. </p> <p> Crear un nuevo Droplet – especificar un nombre, tamaño y ubicación. Para la imagen, haga clic en la pestaña “Aplicaciones” y seleccione la aplicación Dokku. Asegúrese de seleccionar su clave SSH. </p> <p> Una vez creado, completar la configuración mediante la introducción de la dirección IP de la gotita de nueva creación en el navegador, que le llevará a la pantalla de configuración Dokku. Confirmar que la clave pública es correcta, haga clic en “Finalizar configuración”. </p> <p> Ahora el VPS puede aceptar empujones. </p> <h3> Implementar Config </h3> <h3> actualización app.py: </h3> <p> <code>if __name__ == '__main__':<br /> port = int(os.environ.get('PORT', 5000))<br /> app.run(host='0.0.0.0', port=port)<br /> </code> </p> <p> Así, en primer lugar tratar de agarrar el puerto desde el entorno de la aplicación, y si no lo encuentra, el valor predeterminado es el puerto 5000. </p> <p> Asegúrese de actualizar las importaciones, así: </p> <p> <code>import os<br /> </code> </p> <h3> Implementar! </h3> <p> confirmar los cambios, a continuación, empuje: git push Dokku maestro. Si todo va bien, debería ver el URL de la aplicación en su terminal: </p> <p> <code>=====> Application deployed:<br /> http://192.241.208.61:49155<br /> </code> </p> <p> probarlo. Vaya a http://192.241.208.61:49155. (Una vez más, asegúrese de añadir su dirección IP junto con el puerto correcto.) Usted debe ver a su aplicación en vivo! (Ver la imagen en la parte superior de este post para una vista previa.) </p> <h2> próximos pasos </h2> <p> Quieres llevar esto al siguiente nivel? Añadir las siguientes características para la aplicación: </p> <p> Estas características (! Y más) se incluirá en la próxima edición de los cursos de Python real, llegando a principios de octubre 2014! </p> <p> comentario a continuación si tiene alguna pregunta. </p> <p> Salud! </p> </div><!-- .entry-content --> </div><!-- .post-inner --> <div class="section-inner"> </div><!-- .section-inner --> </article><!-- .post --> <div class="pagination-wrapper section-inner"> <hr class="styled-separator pagination-separator is-style-wide" aria-hidden="true" /> <nav class="navigation pagination" role="navigation" aria-label="Entradas"> <h2 class="screen-reader-text">Navegación de entradas</h2> <div class="nav-links"><a class="prev page-numbers" href="https://eltecnofilo.es/category/python/"><span aria-hidden="true">←</span> <span class="nav-prev-text">Entradas <span class="nav-short">siguientes</span></span></a> <a class="page-numbers" href="https://eltecnofilo.es/category/python/">1</a> <span aria-current="page" class="page-numbers current">2</span> <a class="page-numbers" href="https://eltecnofilo.es/category/python/page/3/">3</a> <span class="page-numbers dots">…</span> <a class="page-numbers" href="https://eltecnofilo.es/category/python/page/21/">21</a> <a class="next page-numbers" href="https://eltecnofilo.es/category/python/page/3/"><span class="nav-next-text">Entradas <span class="nav-short">anteriores</span></span> <span aria-hidden="true">→</span></a></div> </nav> </div><!-- .pagination-wrapper --> </main><!-- #site-content --> <div class="footer-nav-widgets-wrapper header-footer-group"> <div class="footer-inner section-inner"> <aside class="footer-widgets-outer-wrapper" role="complementary"> <div class="footer-widgets-wrapper"> <div class="footer-widgets column-one grid-item"> <div class="widget widget_search"><div class="widget-content"><form role="search" method="get" class="search-form" action="https://eltecnofilo.es/"> <label for="search-form-2"> <span class="screen-reader-text">Buscar:</span> <input type="search" id="search-form-2" class="search-field" placeholder="Buscar …" value="" name="s" /> </label> <input type="submit" class="search-submit" value="Buscar" /> </form> </div></div> <div class="widget widget_recent_entries"><div class="widget-content"> <h2 class="widget-title subheading heading-size-3">Entradas recientes</h2> <ul> <li> <a href="https://eltecnofilo.es/vps-cloud-hosting/">VPS cloud hosting</a> </li> <li> <a href="https://eltecnofilo.es/versiones-de-ejecucion-de-python-en-acoplable-como-probar-la-ultima-release-python/">Versiones de ejecución de Python en acoplable: Cómo probar la última Release Python</a> </li> <li> <a href="https://eltecnofilo.es/leer-y-escribir-archivos-csv/">Leer y escribir archivos CSV</a> </li> <li> <a href="https://eltecnofilo.es/python-puro-vs-vs-numpy-tensorflow-comparacion-de-rendimiento/">Python puro vs vs NumPy TensorFlow Comparación de Rendimiento</a> </li> <li> <a href="https://eltecnofilo.es/estructura-python-programa-lexico/">Estructura Python Programa léxico</a> </li> </ul> </div></div><div class="widget widget_recent_comments"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Comentarios recientes</h2><ul id="recentcomments"><li class="recentcomments"><span class="comment-author-link"><a href="https://wordpress.org/" rel="external nofollow ugc" class="url">A WordPress Commenter</a></span> en <a href="https://eltecnofilo.es/hello-world/#comment-1">Hello world!</a></li></ul></div></div> </div> <div class="footer-widgets column-two grid-item"> <div class="widget widget_archive"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Archivos</h2> <ul> <li><a href='https://eltecnofilo.es/2020/04/'>abril 2020</a></li> <li><a href='https://eltecnofilo.es/2020/03/'>marzo 2020</a></li> <li><a href='https://eltecnofilo.es/2019/12/'>diciembre 2019</a></li> </ul> </div></div><div class="widget widget_categories"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Categorías</h2> <ul> <li class="cat-item cat-item-22 current-cat"><a aria-current="page" href="https://eltecnofilo.es/category/python/">Python</a> </li> <li class="cat-item cat-item-1"><a href="https://eltecnofilo.es/category/uncategorized/">Uncategorized</a> </li> </ul> </div></div><div class="widget widget_meta"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Meta</h2> <ul> <li><a rel="nofollow" href="https://eltecnofilo.es/wp-login.php">Acceder</a></li> <li><a href="https://eltecnofilo.es/feed/">Feed de entradas</a></li> <li><a href="https://eltecnofilo.es/comments/feed/">Feed de comentarios</a></li> <li><a href="https://es.wordpress.org/">WordPress.org</a></li> </ul> </div></div> </div> </div><!-- .footer-widgets-wrapper --> </aside><!-- .footer-widgets-outer-wrapper --> </div><!-- .footer-inner --> </div><!-- .footer-nav-widgets-wrapper --> <footer id="site-footer" role="contentinfo" class="header-footer-group"> <div class="section-inner"> <div class="footer-credits"> <p class="footer-copyright">© 2020 <a href="https://eltecnofilo.es/">My Blog</a> </p><!-- .footer-copyright --> <p class="powered-by-wordpress"> <a href="https://es.wordpress.org/"> Funciona gracias a WordPress </a> </p><!-- .powered-by-wordpress --> </div><!-- .footer-credits --> <a class="to-the-top" href="#site-header"> <span class="to-the-top-long"> Ir arriba <span class="arrow" aria-hidden="true">↑</span> </span><!-- .to-the-top-long --> <span class="to-the-top-short"> Subir <span class="arrow" aria-hidden="true">↑</span> </span><!-- .to-the-top-short --> </a><!-- .to-the-top --> </div><!-- .section-inner --> </footer><!-- #site-footer --> <script src='https://eltecnofilo.es/wp-includes/js/wp-embed.min.js?ver=5.3.3'></script> <script> /(trident|msie)/i.test(navigator.userAgent)&&document.getElementById&&window.addEventListener&&window.addEventListener("hashchange",function(){var t,e=location.hash.substring(1);/^[A-z0-9_-]+$/.test(e)&&(t=document.getElementById(e))&&(/^(?:a|select|input|button|textarea)$/i.test(t.tagName)||(t.tabIndex=-1),t.focus())},!1); </script> </body> </html>