【问题标题】:Python os.environ throws key error?Python os.environ 抛出关键错误?
【发布时间】:2016-09-01 20:33:48
【问题描述】:

我正在使用os.environ.get 访问脚本中的环境变量,它抛出了KeyError。它不会从 Python 提示符抛出错误。这是在 OS X 10.11.6 上运行的,并且是 Python 2.7.10。

发生了什么事?

$ python score.py
Traceback (most recent call last):
  File "score.py", line 4, in <module>
    setup_logging()
  File "/score/log.py", line 29, in setup_logging
    config = get_config()
  File "/score/log.py", line 11, in get_config
    environment = os.environ.get('NODE_ENV')
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/UserDict.py", line 23, in __getitem__
    raise KeyError(key)
KeyError: 'NODE_ENV'
$ python -c "import os; os.environ.get('NODE_ENV')"
$

根据要求,这是score.py的源代码

from __future__ import print_function

from log import get_logger, setup_logging
setup_logging()
log = get_logger('score')

这里是log.py

import json
import os
import sys

from iron_worker import IronWorker
from logbook import Logger, Processor, NestedSetup, StderrHandler, SyslogHandler

IRON_IO_TASK_ID = IronWorker.task_id()

def get_config():
  environment = os.environ.get('NODE_ENV')
  if environment == 'production':
    filename = '../config/config-production.json'
  elif environment == 'integration':
    filename = '../config/config-integration.json'
  else:
    filename = '../config/config-dev.json'

  with open(filename) as f:
    return json.load(f)

def setup_logging():
  # This defines a remote Syslog handler
  # This will include the TASK ID, if defined
  app_name = 'scoreworker'
  if IRON_IO_TASK_ID:
    app_name += '-' + IRON_IO_TASK_ID

  config = get_config()

  default_log_handler = NestedSetup([
    StderrHandler(),
    SyslogHandler(
      app_name,
      address = (config['host'], config['port']),
      level = 'ERROR',
      bubble = True
    )
  ])
  default_log_handler.push_application()

def get_logger(name):
  return Logger(name)

【问题讨论】:

  • 你能提供score.py的代码吗?
  • 无法复制...
  • 这很奇怪。 get 永远不应该抛出 KeyError;如果找不到密钥(或者如果您提供了任何默认值),它应该返回None。哎呀,该方法的 source code 根本不应该有 raise KeyError(key) 行!
  • 您会遇到这种情况吗:stackoverflow.com/a/26906934/3642398?我不知道这可能会发生(堆栈跟踪显示当前代码,但从.pyc 文件执行代码),但似乎是该用户所描述的。
  • @Two-BitAlchemist -- 是的,这也是我的本地 python 安装(2.7.10)上的样子。但奇怪的是UserDict.get(UserDict.py 中的第 61 行)应该在回溯中——但我没有看到它。这几乎就像有人修补了 UserDict.get = UserDict.__getitem__ 的猴子,但这将是一件非常阴暗的事情......

标签: python python-2.7


【解决方案1】:

尝试运行:

find . -name \*.pyc -delete

删除您的.pyc 文件。

研究您的问题时,我遇到了this question,其中一位用户遇到了同样的事情:.get() 似乎提出了KeyError。在这种情况下,根据this accepted answer,它是由.pyc 文件引起的,该文件包含通过键(即mydict['potentially_nonexistent_key'])访问dict 值的代码,而回溯显示来自使用了.get() 的更新的.py 文件。我从未听说过这种情况,其中回溯引用了 .py 文件中的当前代码,但显示了由过时的 .pyc 文件引发的错误,但它似乎在 Python 的历史中至少发生过一次。 .

这是一个远射,但我认为值得一试。

【讨论】:

  • 我已经见过几十次了,即.pyc 文件中具有较新日期的文件。当您在运行旧代码后移至旧代码时,像 git 之类的源代码控制可能会导致它。还看到人们将他们的 .pyc 文件放入 repos 的案例(应该避免使用 .gitignore)
  • @Fruch 绝对。我被相关问题所困扰,但这个特定的问题对我来说是新的。
  • 对我不起作用.. 直到我在添加环境变量(VS Code)后退出并重新加载我的 IDE
  • 同意@JGFMK
【解决方案2】:

我在设置环境变量而不导出它时遇到了类似的错误。所以如果你这样做:

me@host:/# NODE_ENV=foo

你会得到这个:

me@host:/# python3
Python 3.8.2 (default, Apr 27 2020, 15:53:34) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> node_env = os.environ['NODE_ENV']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/os.py", line 675, in __getitem__
raise KeyError(key) from None
KeyError: 'NODE_ENV'
>>>

但如果你这样做:

me@host:/# NODE_ENV=foo
me@host:/# export NODE_ENV

有效:

me@host:/# python3
Python 3.8.2 (default, Apr 27 2020, 15:53:34) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> node_env = os.environ['NODE_ENV']
>>> print(node_env)
foo
>>>

【讨论】:

    【解决方案3】:

    windows 删除 .pyc 文件的命令:

    del /S *.pyc
    

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题。我通过对 .env 文件进行一些更正解决了这个问题:

      之前:

      Key = Value
      

      经过我的更正:

      Key=Value 
      

      没有空格并且有效!

      【讨论】:

        【解决方案5】:

        我建议你开始调试 os.py,例如,在 windows 上它正在使用这个实现:

        def get(self, key, failobj=None):
            print self.data.__class__
            print key
            return self.data.get(key.upper(), failobj)
        

        如果我用这个来测试它:

        import os
        
        
        try:
            os.environ.get('NODE_ENV')
        except Exception as e:
            print("-->{0}".format(e.__class__))
        
        os.environ['NODE_ENV'] = "foobar"
        
        try:
            os.environ.get('NODE_ENV')
        except Exception as e:
            print("{0}".format(e.__class__))
        

        输出将是:

        <type 'dict'>
        PYTHONUSERBASE
        <type 'dict'>
        APPDATA
        <type 'dict'>
        NODE_ENV
        <type 'dict'>
        NODE_ENV
        

        因此,阅读dict.get docs 时不会产生异常是有道理的。

        无论如何,如果您不想弄乱或调试python模块,请尝试清理*.pyc文件,尝试正确设置NODE_ENV。如果所有这些都不起作用,请重新启动终端以进行清理。

        【讨论】:

        • OP 正在使用os.environ.get。 当然这可以抛出KeyError。这没有争议或意外。
        • “我已经能够用这个完全不同的代码重现异常”——这对解决 OP 的问题有何帮助?
        • @poke 不同的代码?来吧,这是同样的例外,我想我给出了解决方案Why not trying setting properly that NODE_ENV var?,首先确认......然后只是投反对票,叹息......:P
        • 我可以通过 raise KeyError('NODE_ENV') 得到同样的例外——这有帮助吗?不。OP 使用与您完全不同的方式来访问环境变量,当密钥不存在时,这种方式应该不引发异常。这就是这里要解决的问题。
        • 但是调用.get 是一种避免异常的方法!而且它不起作用。
        猜你喜欢
        • 2012-06-09
        • 2020-10-10
        • 1970-01-01
        • 2021-04-09
        • 1970-01-01
        • 1970-01-01
        • 2013-08-12
        • 2023-03-20
        • 2018-03-28
        相关资源
        最近更新 更多