Hoe om te gaan met mislukte importen van toekomstige functies (__future__) als gevolg van een oude interpreterversie?

Hoe ga je op een elegante manier om met mislukte toekomstige importen van functies? Als een gebruiker Python 2.5 gebruikt en het eerste statement in mijn module is:

from __future__ import print_function

Het compileren van deze module voor Python 2.5 zal mislukken met een:

 File "__init__.py", line 1
    from __future__ import print_function
SyntaxError: future feature print_function is not defined

Ik wil de gebruiker informeren dat hij het programma opnieuw moet uitvoeren met Python >= 2.6 en misschien wat instructies geven over hoe dit te doen. Maar om PEP 236te citeren:

De enige regels die eerder kunnen verschijnen
een future_statement zijn:

  • De module docstring (indien aanwezig).
  • Opmerkingen.
  • Lege regels.
  • Andere future_statements.

Dus ik kan zoiets niet doen:

import __future__
if hasattr(__future__, 'print_function'):
    from __future__ import print_function
else:
    raise ImportError('Python >= 2.6 is required')

Omdat het oplevert:

 File "__init__.py", line 4
    from __future__ import print_function
SyntaxError: from __future__ imports must occur at the beginning of the file

Dit fragment uit de PEP lijkt hoop te geven om het inline te doen:

V: Ik wil future_statements inpakken
in try/behalve blokken, zodat ik kan gebruiken
verschillende code afhankelijk van welke
versie van Python die ik gebruik. Waarom
kan ik niet?

A: Sorry! probeer/behalve is een runtime
voorzien zijn van; future_statements zijn
voornamelijk gimmicks tijdens het compileren, en
je try/behalve gebeurt lang na de
compiler is klaar. Dat wil zeggen, door de
keer dat je het probeert / behalve, de semantiek
die van kracht zijn voor de module zijn al a
uitgemaakte zaak. Sinds de try/behalve
zou niet bereiken wat het lijkt
zoals het zou moeten bereiken, het is gewoon
niet toegestaan. We willen ook houden
deze speciale uitspraken zijn heel gemakkelijk te
vinden en herkennen.

Merk op dat u kunt__future__ importeren
direct, en gebruik de informatie in
het, samen met sys.version_info, om
erachter te komen waar de release je bent
lopen onder stands in relatie tot a
gegeven functiestatus.

Ideeën?


Antwoord 1, autoriteit 100%

“Ik wil de gebruiker laten weten dat ze het programma opnieuw moeten uitvoeren met Python >= 2.6 en misschien wat instructies geven over hoe dit te doen.”

Is daar niet een README-bestand voor?

Hier is uw alternatief. Een “wrapper”: een kleine klodder Python die de omgeving controleert voordat je je doel aop uitvoert.

Bestand: appwrapper.py

import sys
major, minor, micro, releaselevel, serial = sys.version_info
if (major,minor) <= (2,5):
    # provide advice on getting version 2.6 or higher.
    sys.exit(2)
import app
app.main()

Wat ‘directe import’ betekent. U kunt de inhoud van __future__bekijken. Je bent nog steeds gebonden aan het feit dat de a from __future__ import print_functioninformatie is voor de compiler, maar je kunt rondneuzen voordat je de module importeert die het echte werk doet.

import __future__, sys
if hasattr(__future__, 'print_function'): 
    # Could also check sys.version_info >= __future__. print_function.optional
    import app
    app.main()
else:
    print "instructions for upgrading"

Antwoord 2, autoriteit 78%

Een nogal hacky maar eenvoudige methode die ik eerder heb gebruikt, is om gebruik te maken van het feit dat byte-letterwoorden zijn geïntroduceerd in Python 2.6 en zoiets als dit te gebruiken bij het begin van het bestand:

b'This module needs Python 2.6 or later. Please do xxx.'

Dit is ongevaarlijk in Python 2.6 of later, maar een SyntaxErrorin eerdere versies. Iedereen die je bestand probeert te compileren, krijgt nog steeds een foutmelding, maar ze krijgen ook het bericht dat je wilt geven.

Je zou kunnen denken dat, aangezien je deze regel moet hebben na je from __future__ import print_function, het de import zal zijn die de SyntaxErrorgenereert en je zult niet krijg de nuttige foutmelding te zien, maar vreemd genoeg heeft de latere fout voorrang. Ik vermoed dat, aangezien de fout van de import op zichzelf niet echt een syntaxisfout is, deze niet wordt gegenereerd bij de eerste compilatie, en dus worden echte syntaxisfouten het eerst verhoogd (maar ik gok).

Dit voldoet misschien niet aan je criteria om ‘gracieus’ te zijn, en het is erg Python 2.6-specifiek, maar het is snel en gemakkelijk te doen.


Antwoord 3, autoriteit 67%

Plaats een opmerking op dezelfde regel met de "from __future__ import ...", zoals deze:

from __future__ import print_function, division  # We require Python 2.6 or later

Aangezien Python de regel met de fout weergeeft, krijg je een mooie, beschrijvende fout als je de module probeert uit te voeren met Python 2.5:

   from __future__ import print_function, division  # We require Python 2.6 or later
SyntaxError: future feature print_function is not defined

Other episodes