从同一个库导入两次插件版本问题

时间:2013-11-21 00:34:24

标签: python python-2.7 python-2.6

我有一些代码应该使用syslog记录错误。登录到syslog时,我希望脚本名称和pid显示在日志本身中。

from syslog import syslog, openlog, LOG_PID
from sys import version_info

openlog(logoption=LOG_PID)
syslog('Some message')

然而,python 2.6不支持openlog,logoption和LOG_PID,我知道这个脚本将在使用python 2.7和python 2.6的机器上运行。我这样解决了。

from syslog import syslog
from sys import version_info

(major, minor, dummy1, dummy2, dummy3) = version_info
if major == 2 and minor == 7:
    from syslog import openlog, LOG_PID
    openlog(logoption=LOG_PID)

syslog('some message')

这样做会让人感到奇怪。这听起来不错?无论如何我还能在2.6中获得相同的功能吗?

2 个答案:

答案 0 :(得分:3)

首先:

  

从同一个图书馆导入两次

我不确定你认为这个问题是什么,因为你从来没有暗示它是什么。如果多次导入库,则库实际上只会导入一次,但每次都会发生作为导入过程发生的任何名称绑定。

“但”通常不是问题,但如果您尝试使用from MODULE import NAME语法,并且其中一个名称与模块本身具有相同的名称,则很容易让自己感到困惑。

最好的解决方案是不要这样做。例如:

import syslog
# …
syslog.openlog(logoption=syslog.LOG_PID)

如果您确实需要from导入,请确保仅在所有其他from foo import foo导入后执行from foo import bar,这样可以避免任何混淆。


接下来,你的基本前提是错误的:

  

但是,python 2.6不支持openlog,logoption和LOG_PID

是的。 openlog函数从一开始就在模块中。 SO有LOG_PIDHere are the 2.6 docs。这是我使用它:

$ python2.6
Python 2.6.7 (r267:88850, Oct 11 2012, 20:15:00)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from syslog import openlog, LOG_PID
>>> openlog('syslog', LOG_PID)

如果您在导入时遇到错误,很可能它与Python版本无关,而是与您的平台无关。正如文档所说,所有日志选项仅在“<syslog.h>中定义时才可用”。因此,如果您的平台没有LOG_PID,那么Python(无论是2.6还是2.7)将不会在该平台上拥有syslog.LOG_PID

是的,2.6不保证openlog接受关键字参数,而2.7确实。{1>}。但这种差异不可能导致ImportError。防范这种情况的方法不仅仅是跳过调用2.6中的函数;它是在没有关键字参数的情况下调用函数,因此它在两个版本中都能正常工作。


与此同时,你说这很奇怪:

(major, minor, dummy1, dummy2, dummy3) = version_info
if major == 2 and minor == 7:

...但仅仅因为它过于冗长,而且取决于version_info元组在此版本和所有未来版本中将始终具有5个组件的事实。这样做的惯用方法是:

if version_info >= (2, 7):

如果你不明白为什么会这样,请阅读Comparisons上的文档,然后在比较不同的元组之前进行比较。

然而,检查名称而不是检查版本甚至更好。只需try,即可使用ImportError和后备代码处理相关的NameErrorexcept。 Mateo的答案显示了如何做到这一点:

try:
    from syslog import syslog, openlog, LOG_PID
    openlog('syslog', LOG_PID)
except ImportError:
    from syslog import syslog

除此之外,这意味着您不必猜测或弄清楚添加了哪些版本,并冒着猜测错误的风险 - 就像您在这种情况下所做的那样。


下一步:

  

无论如何我还能在2.6中获得相同的功能吗?

当然,但不是使用stdlib syslog模块。它不像2.6中的功能,但只是隐藏在用户之外,它不存在。

如果您search PyPI for syslog,您会发现可以使用的各种第三方模块。

但如果您的平台syslog没有LOG_PID,那么您所做的任何事情都不会使syslog接受该选项。

您可能希望将loggingSysLogHandler一起使用,并在 Python 级别而不是 syslog 级别配置它。< / p>

或者,您可以坚持使用syslog并手动将pid粘贴到消息上 - 这是一个可怕的黑客攻击,但如果平台的syslog没有记录pids并且您拒绝使用任何内容,那么您还要做什么?但系统日志?

答案 1 :(得分:1)

我认为你可以尝试:除外。类似的东西:

try:
    from syslog import openlog, LOG_PID
    openlog(logoption=LOG_PID)
except ImportError:
    from syslog import syslog

这使得它不具有特定版本。

完全披露:当我尝试做类似的事情时,我从Best way to import version-specific python modules得到了这个答案。