我编写了一个简单的Python应用程序,它给出了一个IP地址和端口,然后应用程序在IP:PORT上找到了监听PID。
我希望听到对现行守则的建设性批评。
import argparse
import sys
import socket
import subprocess
import os
def is_legal_ip(address):
ip = address.split(":")
pieces = ip[0].split('.')
if len(pieces) != 4:
return False
try:
return all(0<=int(p)<256 for p in pieces)
except ValueError:
return False
def parse_arguments():
if len(sys.argv) > 2 or len(sys.argv) == 1:
print("Please provide a single argument.")
exit(1)
parser = argparse.ArgumentParser("Returns a PID listenning on IP:PORT")
parser.add_argument('ip_port', metavar='IP:PORT', type=str, nargs=1, help='local address')
args = parser.parse_args()
if (is_legal_ip(args.ip_port[0]) == False):
print("Invalid IP address.")
exit(1)
return(args.ip_port[0])
def address_to_pid(ip_port):
devnull = open(os.devnull, 'w')
output = subprocess.check_output("netstat -nptl".split(), stderr = devnull).splitlines()
devnull.close()
for line in output[2::]:
raw_line = line.split()
if raw_line[3] == ip_port:
if raw_line[6] == "-":
return "No PID listening on address"
else:
return raw_line[6].split(r"/")[0]
def main():
ip_port = parse_arguments()
print address_to_pid(ip_port)
if __name__ == "__main__": main()发布于 2015-07-28 20:55:55
首先,有几个简单的提示:
x == False,而是使用not x,例如在if (is_legal_ip(args.ip_port[0]) == False)中import socket)all(0 <= int(p) < 256 for p in pieces)if __name__ == "__main__": main()中argparse无需亲自与sys.args合作。例如,您可以简单地删除这些行:
如果len(sys.argv) >2或len(sys.argv) == 1: print(“请提供一个参数”)。出口(1)
按照您使用nargs=1指定ip端口参数的方式,argparse将负责验证命令行参数的数量。
你可以省略nargs=1。但是在这种情况下,args.ip_port的值将不是一个列表,而是一个简单的字符串。
您也可以省略type=str,因为这是默认的。
您的使用将变得更简单:
parser.add_argument('ip_port', metavar='IP:PORT', help='local address')
args = parser.parse_args()
if not is_legal_ip(args.ip_port):
parser.error("Invalid IP address.")
return args.ip_port使用ip:port是很尴尬的,多个地方的分裂只是噪音。使用两个参数而不是一个参数将更简单、更简洁:
parser.add_argument('ip', help='local address')
parser.add_argument('port', type=int, help='local port')
args = parser.parse_args()
if not is_legal_ip(args.ip):
parser.error("Invalid IP address.")
return args.ip, args.port请注意,通过这种方式,argparse可以负责验证端口号。
然后,在您的main函数中,您可以获得如下所示的ip地址和端口对:
ip, port = parse_arguments()argparse的错误报告功能
而不是这样:
如果不是is_legal_ip(args.ip_port):打印(“无效IP地址。”)出口(1)
我建议这样做:
if not is_legal_ip(args.ip_port):
parser.error("Invalid IP address.")argparse将与错误消息一起打印使用帮助,并退出。
这里的一个微妙之处是,在本例中,argparse将与代码2一起退出,这在UNIX命令参数无效的情况下是常见的。
在处理文件时,请使用with:
with open(os.devnull, 'w') as devnull:
output = subprocess.check_output("netstat -nl".split(), stderr=devnull).splitlines()这使得devnull.close()没有必要,在退出块时,Python会调用它。
发布于 2015-07-28 20:59:55
您有一些间距问题,例如,这一行:
return all(0<=int(p)<256 for p in pieces)应扩大到以下方面:
return all(0 <= int(p) < 256 for p in pieces)您也有一些不必要的括号。这一行:
return(args.ip_port[0])应改为:
return args.ip_port[0]这一行:
if (is_legal_ip(args.ip_port[0]) == False):也应改为:
if is_legal_ip(args.ip_port[0]) == False:您还应该在函数之间有两个空行,而不是一个。
您还应该阅读PEP8,这是Python的官方风格指南。
您还应该使用上下文管理器来打开和关闭文件,而不是file.close。例如,这段代码:
devnull = open(os.devnull, 'w')
output = subprocess.check_output("netstat -nptl".split(), stderr = devnull).splitlines()
devnull.close()应改为:
with open(os.devnull, 'w') as devnull:
output = subprocess.check_output("netstat -nl".split(), stderr=devnull).splitlines()这段代码:
for line in output[2::]:
raw_line = line.split()
if raw_line[3] == ip_port:
if raw_line[6] == "-":
return "No PID listening on address"
else:
return raw_line[6].split(r"/")[0]可缩短为:
for line in output[2::]:
raw_line = line.split()
if raw_line[3] == ip_port and if raw_line[6] == "-":
return "No PID listening on address"
return raw_line[6].split(r"/")[0]这一条件:
if len(sys.argv) > 2 or len(sys.argv) == 1:也可缩短为:
if len(sys.argv) >= 1:此外
发布于 2015-07-31 14:23:38
您可以尝试类似于上述建议的pep8,并利用Python中的一些内置内容。
注意:这假设您希望查找特定的IPv4 NetAddr,而不仅仅是侦听内容。例如,下面的代码将不使用IPv6地址(没有mods),也不会捕获监听*(例如SSH)的内容。这也是python3友好的(尽管您可能需要调整psutil的一些东西才能使它与python3一起工作,但是python3语句已经准备好了。)
'''
my program does cool stuff
'''
import argparse
import psutil
from ipaddress import IPv4Network, AddressValueError
def is_legal_ip(address):
'''
determine if IP is valid
'''
address = address[0]
try:
if IPv4Network(unicode(address)):
pass
except AddressValueError as valueerr:
print('invalid IP provided: {} : {}'.format(address, valueerr))
return False
return True
def parse_arguments():
'''
parse the command line arguments
'''
parser = argparse.ArgumentParser('Returns a PID listenning on IP:PORT')
parser.add_argument('ip_address',
type=str,
nargs=1,
help='local address')
parser.add_argument('ip_port',
type=int,
nargs=1,
help='local port')
args = parser.parse_args()
if not is_legal_ip(args.ip_address):
parser.error('Invalid IP address : {}'.format(args.ip_address))
return(args.ip_address, args.ip_port)
def address_to_pid(ip_address='', ip_port=0):
'''
determine pid based on IP and port combo
leverage psutil library and net_connections method
return the pid of the listening binary
'''
possible_pids = set()
[x.pid for x in psutil.net_connections() if x.laddr == (
str(ip_address), ip_port) and x.pid not in possible_pids\
and possible_pids.add(x.pid)]
if len(possible_pids) < 1:
return 'Nothing'
return possible_pids.pop()
def main():
'''
a small program to get the PID listening on an IP/port combo
'''
ip_address, ip_port = parse_arguments()
actual_pid = address_to_pid(ip_address[0], ip_port[0])
print('{} is listening on {} port {}'.format(actual_pid,
ip_address,
ip_port))
if __name__ == '__main__':
main()https://codereview.stackexchange.com/questions/98377
复制相似问题