2
votes

Comment remplacer has_key en python3?

J'essaie d'installer Auto-SelfControl et je suis resté bloqué lors de l'exécution de cette commande:

def check_config(config):
""" checks whether the config file is correct """
if not config.has_key("username"):
    exit_with_error("No username specified in config.")
if config["username"] not in get_osx_usernames():
    exit_with_error(
            "Username '{username}' unknown.\nPlease use your OSX username instead.\n" \
            "If you have trouble finding it, just enter the command 'whoami'\n" \
            "in your terminal.".format(
                    username=config["username"]))
if not config.has_key("selfcontrol-path"):
    exit_with_error("The setting 'selfcontrol-path' is required and must point to the location of SelfControl.")
if not os.path.exists(config["selfcontrol-path"]):
    exit_with_error(
            "The setting 'selfcontrol-path' does not point to the correct location of SelfControl. " \
            "Please make sure to use an absolute path and include the '.app' extension, " \
            "e.g. /Applications/SelfControl.app")
if not config.has_key("block-schedules"):
    exit_with_error("The setting 'block-schedules' is required.")
if len(config["block-schedules"]) == 0:
    exit_with_error("You need at least one schedule in 'block-schedules'.")
if config.get("host-blacklist", None) is None:
    print("WARNING:")
    msg = "It is not recommended to directly use SelfControl's blacklist. Please use the 'host-blacklist' " \
          "setting instead."
    print(msg)
    syslog.syslog(syslog.LOG_WARNING, msg)

Il montre l'erreur:

AttributeError: l'objet 'dict' n'a pas d'attribut 'has_key'

Je cherche des solutions et finis par remplacer has_key par l'opérateur dans mais comme je ne connais que les bases de python, le code est assez complexe pour moi.

Il y a 3 endroits où has_key a été utilisé, pouvez-vous m'aider à le changer pour que je puisse exécuter avec python3?

1 .

def check_if_running(username):
""" checks if self-control is already running. """
defaults = get_selfcontrol_settings(username)
return defaults.has_key("BlockStartedDate") and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])

2-4.

sudo /usr/bin/python auto-selfcontrol.py


6 commentaires

Utilisez Python 2 ou essayez d'utiliser 2to3 .


has_key est obsolète dans Python 3. Pourquoi n'utilisez-vous pas Python 2.7 à la place?


@ anh-nguyen remplace chaque vérification par la syntaxe clé dans dict , par exemple return defaults.has_key ("BlockStartedDate") et non ... remplacer par retourner "BlockStartedDate" par défaut et non ...


Copie possible de Dois-je utiliser 'has_key () 'ou' in 'sur les dictionnaires Python?


@Selcuk: Étant donné que la fin de vie de Python 2 est dans moins d'un an (la fin de vie est le 1er janvier 2020), migrer (par exemple avec 2to3 ) est probablement une bonne idée.


@ShadowRanger Bon point, mais ce n'est pas comme si Python 2.x disparaîtrait l'année prochaine, ou arrêterait soudainement d'interpréter ce script en question.


4 Réponses :


0
votes

Remplacer comme suit

1.

def check_config(config):
""" checks whether the config file is correct """
if not "username" in config:
    exit_with_error("No username specified in config.")
if config["username"] not in get_osx_usernames():
    exit_with_error(
            "Username '{username}' unknown.\nPlease use your OSX username instead.\n" \
            "If you have trouble finding it, just enter the command 'whoami'\n" \
            "in your terminal.".format(
                    username=config["username"]))
if not "selfcontrol-path" in config:
    exit_with_error("The setting 'selfcontrol-path' is required and must point to the location of SelfControl.")
if not os.path.exists(config["selfcontrol-path"]):
    exit_with_error(
            "The setting 'selfcontrol-path' does not point to the correct location of SelfControl. " \
            "Please make sure to use an absolute path and include the '.app' extension, " \
            "e.g. /Applications/SelfControl.app")
if not "block-schedules" in config:
    exit_with_error("The setting 'block-schedules' is required.")
if len(config["block-schedules"]) == 0:
    exit_with_error("You need at least one schedule in 'block-schedules'.")
if config.get("host-blacklist", None) is None:
    print("WARNING:")
    msg = "It is not recommended to directly use SelfControl's blacklist. Please use the 'host-blacklist' " \
          "setting instead."
    print(msg)
    syslog.syslog(syslog.LOG_WARNING, msg)

2-4.

def check_if_running(username):
""" checks if self-control is already running. """
defaults = get_selfcontrol_settings(username)
return "BlockStartedDate" in defaults and not NSDate.distantFuture().isEqualToDate_(defaults["BlockStartedDate"])


0 commentaires

1
votes

Une source formelle de la solution est ici: https: //portingguide.readthedocs. io / fr / latest / dicts.html

Le TL; DR est le suivant:

if "selfcontrol-path" not in config:
    # do something

Est maintenant:

if not config.has_key("selfcontrol-path"):
    # do something


0 commentaires

4
votes

Bien que les solutions au coup par coup dans les autres réponses fonctionnent, cette approche est imparfaite simplement parce qu'il est trop facile de faire une petite erreur, de rater un endroit qui doit être réparé, etc. La meilleure solution est d'utiliser simplement le 2to3 convertisseur . Vous pouvez réparer tous vos fichiers d'un seul coup avec:

$ 2to3 -f has_key -w auto-selfcontrol.py

Cela ne fonctionne que le has_key fixateur qui convertit de dict.has_key (clé) en clé dans dict code>. Bien sûr, vous pouvez faire le correctif vous-même, mais c'est un cas où de simples correcteurs programmatiques fonctionnent très bien. Vous voudrez peut-être simplement l'exécuter sans -f has_key pour qu'il applique tous les fixateurs à la fois, au cas où d'autres changements de rupture s'appliqueraient entre Py2 et Py3.

2to3 gère à peu près tout automatiquement, à l'exception des changements de type Py2 str (où c'est une décision de logique de code sur si un littéral str donné doit être octets ou str dans Py3) et division entière (où / peut avoir besoin d'être remplacé par // , en fonction de si le calcul est une division en virgule flottante logique ou une division de plancher). Mais pour has_key , c'est assez fiable.


0 commentaires

1
votes

Testé en python3.7.

   tmp = {'a':1, 'b':2, 'c':3}
   print(tmp.__contains__('a')) #True


0 commentaires