我刚刚完成了一个简单的python脚本,它使用这个模块调用泽诺斯 API来获取活动事件。脚本所做的事情:
POST将一些数据(首先是身份验证)发送给每个数字到具有以下参数的特定URL:phonenr、smstxt、Submit这个脚本本身就说明了问题,它不需要评论。我正在寻找的是脚本/案例中的一些逻辑,这些逻辑我没有涉及到/错误的编码标准/设计模式,还有一些关于如何改进代码的建议(以使每个数字同时接收消息的方式--也许使用多线程会有所帮助)。
包含电话号码的文件如下所示:
phone_no1
phone_no2
..
phone_non守则是:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import urllib2 as urllib
from urllib import urlencode
from os.path import join as joinPath
from traceback import print_tb
from os.path import isfile
from sys import exc_info
import myzenoss
zenoss = myzenoss.Zenoss('ip_of_zenoss', 'admin', 'pass')
hdrs = {'User-Agent': "Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127 Firefox/2.0.0.11"}
gh_url = 'http://ip-for-post/txsms.cgi' # basically this is an IP for a Mobilink which sends the SMS
APPLICATION_PATH = '/srv/sms_alert/'
ALERT_POINT_PATH = joinPath(APPLICATION_PATH, 'alert_contact')
try:
isInProduction = False
for evt in zenoss.get_events():
if evt['prodState'] == 'Production':
isInProduction = True
if isInProduction and isfile(ALERT_POINT_PATH):
alertContactContent = None
with open(ALERT_POINT_PATH, 'r') as alertContactFile:
alertContactContent = alertContactFile.read()
alertContactContent = alertContactContent.splitlines()
if alertContactContent:
evt['summary'] = ':zenoss]\n\nError: {0}'.format(evt['summary'])
evt['device']['text'] = '{0}'.format(evt['device']['text'])
final_message = '{0}\nName: {1}\n\n'.format(evt['summary'], evt['device']['text'])
for alertContactContentLine in alertContactContent:
data = {'phonenr': alertContactContentLine, 'smstxt': str(final_message), 'Submit': 'SendSms'}
data = urlencode(data)
req = urllib.Request(gh_url, data, headers=hdrs)
password_manager = urllib.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, gh_url, 'admin', 'password')
auth_manager = urllib.HTTPBasicAuthHandler(password_manager)
opener = urllib.build_opener(auth_manager)
urllib.install_opener(opener)
handler = urllib.urlopen(req)
break # used this to only get the last event
else:
evt['summary'] = '#[ERROR: SMS ALERT NO CONTACT]# {0}'.format(evt['summary'])
except Exception as e:
ex_type, ex, tb = exc_info()
print('\n #[ERROR]# TRANSFORM: exception: {ex}\n'.format(ex=e))
print('\n #[ERROR]# TRANSFORM: exception traceback: {trace}\n'.format(trace=print_tb(tb)))发布于 2016-03-22 21:19:21
我建议使用“警卫条款”。目前,您有大量的缩进可以用这些移除。
采取:
如果isInProduction和isfile(ALERT_POINT_PATH):alertContactContent = None (ALERT_POINT_PATH,'r')作为alertContactFile: alertContactContent = alertContactFile.read() alertContactContent = alertContactContent.splitlines()
这可能是:
if not (isInProduction and isfile(ALERT_POINT_PATH)):
continue
alertContactContent = None
with open(ALERT_POINT_PATH, 'r') as alertContactFile:
alertContactContent = alertContactFile.read()
alertContactContent = alertContactContent.splitlines()后者要容易得多。更容易读懂这些语句中的多个。
我也会像urllib2一样推荐请求包。
还请参阅:建议将请求包用于更高级别的http客户端接口。
我建议不要检查ALERT_POINT_PATH是否是一个文件,只需尝试打开它。这将防止TOCTOU虫。
要做到这一点,您可以更改:
if isInProduction and isfile(ALERT_POINT_PATH):
alertContactContent = None
with open(ALERT_POINT_PATH, 'r') as alertContactFile:
alertContactContent = alertContactFile.read()
alertContactContent = alertContactContent.splitlines()
...
else:
evt['summary'] = '#[ERROR: SMS ALERT NO CONTACT]# {0}'.format(evt['summary'])转入:
try:
with open(ALERT_POINT_PATH, 'r') as f:
alert_contact_content = f.readlines()
except IOError:
evt['summary'] = '#[ERROR: SMS ALERT NO CONTACT]# {0}'.format(evt['summary'])
continue这大大降低了算法的复杂度。
这使用了一个正确的try except,其中指定了错误。而是使用f.readlines()而不是alertContactFile.read().splitlines()。
我建议将您的格式合并成一行:
final_message = ':zenoss]\n\nError: {0}\nName: {1}\n\n'.format(evt['summary'], evt['device']['text'])并用一种理解的方法对所有非evt['prodState'] == 'Production'的evts进行预过滤。
总之,我建议:
def send_error_messages(zenoss):
for evt in (e for e in zenoss.get_events() if e['prodState'] == 'Production'):
try:
with open(ALERT_POINT_PATH, 'r') as f:
alert_contact_content = f.readlines()
except IOError:
evt['summary'] = '#[ERROR: SMS ALERT NO CONTACT]# {0}'.format(evt['summary'])
continue
if not alert_contact_content:
continue
final_message = ':zenoss]\n\nError: {0}\nName: {1}\n\n'.format(evt['summary'], evt['device']['text'])
for phone_address in alert_contact_content:
send_message({'phonenr': phone_address, 'smstxt': final_message, 'Submit': 'SendSms'})
break其中send_message是您的urllib2函数。
发布于 2016-03-22 20:52:38
join_path (如果你真的想重命名它),而不是joinPath等等。format的名称与位置参数有一点不一致;我要说的是,除非您有很多参数,否则通常可以使用未命名的位置,即"{} {}".format(...)。hdrs和evt与headers和event相比并没有多大的节省。os.path的导入被提到了两次,这也可能只是一行。'{0}'.format(...)可能应该是str(...)。在结构上,我看到了一些东西。
try/catch块看起来对Python解释器默认打印的内容没有太大的改进。isInProduction变量,并且考虑到它被设置为True,它看起来根本不需要。或者缩进是错误的,在这种情况下,应该像is_in_production = event['prodState'] == 'Production'那样立即初始化它。alertContactContent一样以这种方式初始化变量在Python中是没用的。我可能会将读取文件和将内容拆分成一个函数改为使用它(比如alert_contact_content = read_and_split(ALERT_POINT_PATH)之类的)。for-loop的主体看起来应该是一个函数,就像create_auth_manager()一样,应该只创建一次--除非我遗漏了一些东西--所有的password_manager实例都是相同的,所以重新使用它们是有意义的。break。或者对它的评论。完全没有。基本上,如果它是结构化的,例如使用函数之类的,那么读取所有这些嵌套的东西就会容易得多。
https://codereview.stackexchange.com/questions/123572
复制相似问题