Python 从同一库导入两次会导致版本问题

Python 从同一库导入两次会导致版本问题,python,python-2.7,python-2.6,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') 然而,Python2.6不支持openlog、logoption和LOG_PID,我知道这个脚本将在使用Python2.7和Python2.6

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

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

openlog(logoption=LOG_PID)
syslog('Some message')
然而,Python2.6不支持openlog、logoption和LOG_PID,我知道这个脚本将在使用Python2.7和Python2.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中获得相同的功能吗?

我想你可以用try:except来实现。比如:

try:
    from syslog import openlog, LOG_PID
    openlog(logoption=LOG_PID)
except ImportError:
    from syslog import syslog
这使得它不那么特定于版本


完全披露:我在尝试做类似的事情时得到了这个答案。

我想你可以用try:except来做。比如:

try:
    from syslog import openlog, LOG_PID
    openlog(logoption=LOG_PID)
except ImportError:
    from syslog import syslog
这使得它不那么特定于版本

完全披露:我在尝试做类似的事情时得到了这个答案。

首先:

从同一库导入两次

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

“但是”通常不是问题,但是如果您试图使用模块导入名称语法中的
,并且其中一个名称与模块本身具有相同的名称,则很容易混淆您自己

最好的解决办法就是不要这样做。例如:

import syslog
# …
syslog.openlog(logoption=syslog.LOG_PID)
如果您确实需要从
导入
,请确保在所有其他
从foo导入栏
导入之后,才从foo导入foo
,这样可以避免任何混淆


其次,你的基本前提是错误的:

但是,Python2.6不支持openlog、logoption和LOG_PID

是的。
openlog
函数从一开始就在模块中。所以有
LOG\u PID
。下面是我在使用它:

$ 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版本无关,而是与您的平台有关。正如文档所说,所有日志选项只有在
中定义的情况下才可用。因此,如果您的平台没有
log\u PID
,那么Python 2.6或2.7在该平台上都不会有
syslog.log\u PID

诚然,2.6并不保证
openlog
采用关键字参数,而2.7保证采用关键字参数。但这种差异不可能导致
ImportError
。防止这种情况发生的方法不是跳过调用2.6中的函数;不使用关键字参数来调用函数是非常困难的,因此它在两个版本中都能正常工作


同时,你是对的,这很奇怪:

(major, minor, dummy1, dummy2, dummy3) = version_info
if major == 2 and minor == 7:
…但这仅仅是因为它过于冗长,这取决于以下事实:
version\u info
元组在此版本和所有未来版本中始终有5个组件。实现这一点的惯用方法是:

if version_info >= (2, 7):
如果您不明白为什么这样做,请阅读上的文档,并尝试比较不同的元组,直到得到它为止

但是,检查名称比检查版本更好。只需
尝试
,并使用
除外
和回退代码处理相关的
导入错误
名称错误
。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中的功能那样,只是对用户隐藏了,它不存在

如果你能找到各种各样的第三方模块,你可以用它们来代替

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

您可能希望将
logging
SysLogHandler
一起使用,并在Python级别而不是syslog级别对其进行配置

或者,您可以坚持使用
syslog
并手动将pid添加到消息上——这是一个可怕的黑客行为,但是如果平台的syslog不记录pid,而您拒绝使用syslog以外的任何东西,您还打算做些什么呢?

首先:

从同一库导入两次

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

“但是”通常不是问题,但是如果您试图使用模块导入名称语法中的
,并且其中一个名称与模块本身具有相同的名称,则很容易混淆您自己

最好的解决办法就是不要这样做。例如:

import syslog
# …
syslog.openlog(logoption=syslog.LOG_PID)
如果您确实需要从
导入
,请确保在所有其他
从foo导入栏
导入之后,才从foo导入foo
,这样可以避免任何混淆


其次,你的基本前提是错误的:

但是,Python2.6不支持openlog、logoption和LOG_PID

是的。
openlog
函数从一开始就在模块中。所以有
LOG\u PID
。下面是我在使用它:

$ 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版本无关,而是与您的平台有关。正如文档所说,所有日志选项只有在
中定义的情况下才可用。因此,如果您的平台没有
log\u PID
,那么Python 2.6或2.7在该平台上都不会有
syslog.log\u PID

的确,2.6并不保证
openlog
接受关键字参数,