Gå til innhold

Anbefalte innlegg

Hei.

 

Jeg er relativt ny på python. Så jeg trenger hjelp til et "enkelt" script, hvor jeg skal kunne "pinge" en enkelt side i en loop... Slik at jeg hele tiden får output av enkeltresultater, skal etterpå forsøke å lage en simpel graph med responstiden... Over et tidsrom av f.eks en time.. Trenger ikke at den pinger så fort den får tilbake pakken, men en pakke pr. sekund skal duge. (3600) pakker, i timen.

 

Vet det finnes ferdig software for dette, men ønsker å lære mer python i denne retningen.

 

Kommer også til å modifisere denne, slik at jeg kan ved hjelp av scriptet/programmet automatisk aktivere backupservere, om hovedserveren min ikke gir en respons, så det må altså kjøre en evig loop, intill jeg velger å stoppe scriptet/lukke programmet.

Lenke til kommentar
Videoannonse
Annonse

Python har ikke direkte støtte for å kunne pinge adresser gjennom sockets. Til dette er andre programmeringsspråk som f.ek.s C/C++/C# å anbefale. Men det finnes en vei man kan pinge via python med, men det blir ikke direkte fint - og heller ikke platformuavhengig. Faktisk vil implementasjonen og kun virke om han som kjører programmet kjører samme språk av operativsystemet som deg og. Måten jeg tenker på er å kjøre ping-applikasjonen som følger med OSet i en subprocess og bare lese resultatet fra pingingen; hvor man gjerne bare filtrere ut de faktiske tallene man er ute etter.

 

import subprocess

host = "www.google.com"

ping = subprocess.Popen(
   ["ping", "-n", "4", host],
   stdout = subprocess.PIPE,
   stderr = subprocess.PIPE,
)

out, error = ping.communicate()
print out

http://stackoverflow.com/questions/316866/ping-a-site-in-python

 

En annen, mer platformuavhengig løsning ville vært:

1: Lage programmet i et annet språk med direkte støtte for å sende ping-pakker.

2: Lage en server og et klient script som du kjører og bare sender data over sockets.

 

Server:

- Lytte på en bestemt port

- Akkeseptere alle tilkoblinger og tildele de en egen "worker"

- Om den mottar "PING XXXX" (hvor XXXX er enten et random tall eller navnet på klienten)

så skal den svare "PONG XXXX" tilbake til klienten.

 

 

Klienten:

- Koble til server på gitt IP og PORT

- Sende PING med bestemt tidsintervall til server

- Hvis ikke ping er svart på innen rimelig tid utfør bestemt oppgave.

 

For å få til dette må du lese deg litt opp på sockets. Finnes masse god dokumenstasjon om det der ute :)

Endret av etse
Lenke til kommentar

Hehe, satt å googlet masse selv, kom over den du linker til.. Selv om jeg ikke er fornøyd med en slik løsning, så fungerer det med subprocess..

 

 

Edit:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import subprocess
import sys
import re
import time


host = "www.NIX.no"
cmd = "ping "+host+" -n 1"


while 1:
ping = subprocess.Popen(
	cmd,
	stdout = subprocess.PIPE,
	stderr = subprocess.PIPE,
)

out, error = ping.communicate()

regex = re.compile("Average = (\d+)ms")
result = regex.findall(out)
print ">>> Ping from: %s" % host

for ping in result:
	print ">>> %s" % ping

time.sleep(2)

 

Planen er å lage en loop, som simpelthen kjører "ping "+host+" -n 1"; benytte meg av regex, for å hente "average = 15ms", spytte ut/printe resultatet, vent 1 sek, og kjør dette om igjen. Skal ikke være vanskelige en som så.

 

Da var jeg godt på vei :))

 

Nå må jeg lage en loop for å kjøre denne flere ganger :p

Endret av tROOP4H
Lenke til kommentar

Scriptet er kommet langt... Fremdeles en bug jeg skal fjerne, og masse aplikasjoner som må legge til, benyttet meg av noe ferdig software for å lage grafen :)...

Har bare testet det på windows xp, husker ikke om win7, og win vista har samme oppsett i kommandolinjen.

 

Krever følgende ekstrapakker:

-wxPython

-Numpy

-matplotlib

 

Edit..: Lagres som xxxx.pyw

 

Scriptet:

 

#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import pprint
import sys
import wx
import subprocess
import re


import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import \
   FigureCanvasWxAgg as FigCanvas, \
   NavigationToolbar2WxAgg as NavigationToolbar
import numpy as np
import pylab

host = "www.NIX.no"
cmd = "ping "+host+" -n 1"
hz = 1000

class DataGen(object):
   def __init__(self, init=0):
       self.data = self.init = init

   def next(self):
       self._recalc_data()
       return self.data

   def _recalc_data(self):
       ping = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
       out, error = ping.communicate()

       regex = re.compile("Average = (\d+)ms")
       result = regex.findall(out)
       for ping in result:
           delta = int(ping)
           self.data = delta


class BoundControlBox(wx.Panel):
   """ A static box with a couple of radio buttons and a text
       box. Allows to switch between an automatic mode and a 
       manual mode with an associated value.
   """
   def __init__(self, parent, ID, label, initval):
       wx.Panel.__init__(self, parent, ID)

       self.value = initval

       box = wx.StaticBox(self, -1, label)
       sizer = wx.StaticBoxSizer(box, wx.VERTICAL)

       self.radio_auto = wx.RadioButton(self, -1, 
           label="Auto", style=wx.RB_GROUP)
       self.radio_manual = wx.RadioButton(self, -1,
           label="Manual")
       self.manual_text = wx.TextCtrl(self, -1, 
           size=(35,-1),
           value=str(initval),
           style=wx.TE_PROCESS_ENTER)

       self.Bind(wx.EVT_UPDATE_UI, self.on_update_manual_text, self.manual_text)
       self.Bind(wx.EVT_TEXT_ENTER, self.on_text_enter, self.manual_text)

       manual_box = wx.BoxSizer(wx.HORIZONTAL)
       manual_box.Add(self.radio_manual, flag=wx.ALIGN_CENTER_VERTICAL)
       manual_box.Add(self.manual_text, flag=wx.ALIGN_CENTER_VERTICAL)

       sizer.Add(self.radio_auto, 0, wx.ALL, 10)
       sizer.Add(manual_box, 0, wx.ALL, 10)

       self.SetSizer(sizer)
       sizer.Fit(self)

   def on_update_manual_text(self, event):
       self.manual_text.Enable(self.radio_manual.GetValue())

   def on_text_enter(self, event):
       self.value = self.manual_text.GetValue()

   def is_auto(self):
       return self.radio_auto.GetValue()

   def manual_value(self):
       return self.value


class GraphFrame(wx.Frame):
   """ The main frame of the application
   """
   title = 'Netgraph Beta 0.1'

   def __init__(self):
       wx.Frame.__init__(self, None, -1, self.title)

       self.datagen = DataGen()
       self.data = [self.datagen.next()]
       self.paused = False

       self.create_menu()
       self.create_status_bar()
       self.create_main_panel()

       self.redraw_timer = wx.Timer(self)
       self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)        
       self.redraw_timer.Start(hz)

   def create_menu(self):
       self.menubar = wx.MenuBar()

       menu_file = wx.Menu()
       m_expt = menu_file.Append(-1, "&Save plot\tCtrl-S", "Save plot to file")
       self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt)
       menu_file.AppendSeparator()
       m_exit = menu_file.Append(-1, "E&xit\tCtrl-X", "Exit")
       self.Bind(wx.EVT_MENU, self.on_exit, m_exit)

       self.menubar.Append(menu_file, "&File")
       self.SetMenuBar(self.menubar)

   def create_main_panel(self):
       self.panel = wx.Panel(self)

       self.init_plot()
       self.canvas = FigCanvas(self.panel, -1, self.fig)

       self.xmin_control = BoundControlBox(self.panel, -1, "X min", 0)
       self.xmax_control = BoundControlBox(self.panel, -1, "X max", 50)
       self.ymin_control = BoundControlBox(self.panel, -1, "Y min", 0)
       self.ymax_control = BoundControlBox(self.panel, -1, "Y max", 100)

       self.pause_button = wx.Button(self.panel, -1, "Pause")
       self.Bind(wx.EVT_BUTTON, self.on_pause_button, self.pause_button)
       self.Bind(wx.EVT_UPDATE_UI, self.on_update_pause_button, self.pause_button)

       self.cb_grid = wx.CheckBox(self.panel, -1, 
           "Show Grid",
           style=wx.ALIGN_RIGHT)
       self.Bind(wx.EVT_CHECKBOX, self.on_cb_grid, self.cb_grid)
       self.cb_grid.SetValue(True)

       self.cb_xlab = wx.CheckBox(self.panel, -1, 
           "Show X labels",
           style=wx.ALIGN_RIGHT)
       self.Bind(wx.EVT_CHECKBOX, self.on_cb_xlab, self.cb_xlab)        
       self.cb_xlab.SetValue(True)

       self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)
       self.hbox1.Add(self.pause_button, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
       self.hbox1.AddSpacer(20)
       self.hbox1.Add(self.cb_grid, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)
       self.hbox1.AddSpacer(10)
       self.hbox1.Add(self.cb_xlab, border=5, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL)

       self.hbox2 = wx.BoxSizer(wx.HORIZONTAL)
       self.hbox2.Add(self.xmin_control, border=5, flag=wx.ALL)
       self.hbox2.Add(self.xmax_control, border=5, flag=wx.ALL)
       self.hbox2.AddSpacer(24)
       self.hbox2.Add(self.ymin_control, border=5, flag=wx.ALL)
       self.hbox2.Add(self.ymax_control, border=5, flag=wx.ALL)

       self.vbox = wx.BoxSizer(wx.VERTICAL)
       self.vbox.Add(self.canvas, 1, flag=wx.LEFT | wx.TOP | wx.GROW)        
       self.vbox.Add(self.hbox1, 0, flag=wx.ALIGN_LEFT | wx.TOP)
       self.vbox.Add(self.hbox2, 0, flag=wx.ALIGN_LEFT | wx.TOP)

       self.panel.SetSizer(self.vbox)
       self.vbox.Fit(self)

   def create_status_bar(self):
       self.statusbar = self.CreateStatusBar()

   def init_plot(self):
       self.dpi = 100
       self.fig = Figure((3.0, 3.0), dpi=self.dpi)

       self.axes = self.fig.add_subplot(111)
       self.axes.set_axis_bgcolor('black')
       self.axes.set_title('Ping host: '+host+'', size=12)

       pylab.setp(self.axes.get_xticklabels(), fontsize=8)
       pylab.setp(self.axes.get_yticklabels(), fontsize=8)

       # plot the data as a line series, and save the reference 
       # to the plotted line series
       #
       self.plot_data = self.axes.plot(
           self.data, 
           linewidth=1,
           color=(1, 1, 0),
           )[0]

   def draw_plot(self):
       """ Redraws the plot
       """
       # when xmin is on auto, it "follows" xmax to produce a 
       # sliding window effect. therefore, xmin is assigned after
       # xmax.
       #
       if self.xmax_control.is_auto():
           xmax = len(self.data) if len(self.data) > 200 else 200
       else:
           xmax = int(self.xmax_control.manual_value())

       if self.xmin_control.is_auto():            
           xmin = xmax - 200
       else:
           xmin = int(self.xmin_control.manual_value())

       # for ymin and ymax, find the minimal and maximal values
       # in the data set and add a mininal margin.
       # 
       # note that it's easy to change this scheme to the 
       # minimal/maximal value in the current display, and not
       # the whole data set.
       # 
       if self.ymin_control.is_auto():
           ymin = round(min(self.data), 0) - 1
       else:
           ymin = int(self.ymin_control.manual_value())

       if self.ymax_control.is_auto():
           ymax = round(max(self.data), 0) + 1
       else:
           ymax = int(self.ymax_control.manual_value())

       self.axes.set_xbound(lower=xmin, upper=xmax)
       self.axes.set_ybound(lower=ymin, upper=ymax)

       # anecdote: axes.grid assumes b=True if any other flag is
       # given even if b is set to False.
       # so just passing the flag into the first statement won't
       # work.
       #
       if self.cb_grid.IsChecked():
           self.axes.grid(True, color='gray')
       else:
           self.axes.grid(False)

       # Using setp here is convenient, because get_xticklabels
       # returns a list over which one needs to explicitly 
       # iterate, and setp already handles this.
       #  
       pylab.setp(self.axes.get_xticklabels(), 
           visible=self.cb_xlab.IsChecked())

       self.plot_data.set_xdata(np.arange(len(self.data)))
       self.plot_data.set_ydata(np.array(self.data))

       self.canvas.draw()

   def on_pause_button(self, event):
       self.paused = not self.paused

   def on_update_pause_button(self, event):
       label = "Resume" if self.paused else "Pause"
       self.pause_button.SetLabel(label)

   def on_cb_grid(self, event):
       self.draw_plot()

   def on_cb_xlab(self, event):
       self.draw_plot()

   def on_save_plot(self, event):
       file_choices = "PNG (*.png)|*.png"

       dlg = wx.FileDialog(
           self, 
           message="Save plot as...",
           defaultDir=os.getcwd(),
           defaultFile="plot.png",
           wildcard=file_choices,
           style=wx.SAVE)

       if dlg.ShowModal() == wx.ID_OK:
           path = dlg.GetPath()
           self.canvas.print_figure(path, dpi=self.dpi)
           self.flash_status_message("Saved to %s" % path)

   def on_redraw_timer(self, event):
       # if paused do not add data, but still redraw the plot
       # (to respond to scale modifications, grid change, etc.)
       #
       if not self.paused:
           self.data.append(self.datagen.next())

       self.draw_plot()

   def on_exit(self, event):
       self.Destroy()

   def flash_status_message(self, msg, flash_len_ms=1500):
       self.statusbar.SetStatusText(msg)
       self.timeroff = wx.Timer(self)
       self.Bind(
           wx.EVT_TIMER, 
           self.on_flash_status_off, 
           self.timeroff)
       self.timeroff.Start(flash_len_ms, oneShot=True)

   def on_flash_status_off(self, event):
       self.statusbar.SetStatusText('')


if __name__ == '__main__':
   app = wx.PySimpleApp()
   app.frame = GraphFrame()
   app.frame.Show()
   app.MainLoop()

 

Endret av tROOP4H
Lenke til kommentar

http://mail.python.org/pipermail/tutor/2009-November/072706.html

 

En som har laget ping i python via icmp raw sockets

 

Edit : also, http://www.g-loaded.eu/2009/10/30/python-ping/

 

Joda, har test dem... De viser dårlige resultater ved lav responstid. Pinget en side via kommandloninja hvor jeg hadde stabilt 7ms...

 

Så testet jeg med de scriptene. Det resulterte i 0.0ms, 15ms, 0.0ms, 15ms... etc.. Så det var dårlig! Testet mot flere hoster, det viste bare korrekt mot sider som jeg hadde 35+ms til.

 

 

 

Tror de fleste er enige med meg når jeg sier så lange script burde legges ut på pastebin i stede for code-tags; slik at det blir lettere å lese.

Så for de som vil lese gjennom den, her: http://pastebin.com/RvXeduE3

Den er ikke oppdatert etter siste edit jeg gjorde, som fikset en del bugs... Men er en kjapp fiks for de med litt kunskap! Ellers får du ha takk for den ;)

Endret av tROOP4H
Lenke til kommentar
Så testet jeg med de scriptene. Det resulterte i 0.0ms, 15ms, 0.0ms, 15ms... etc.. Så det var dårlig! Testet mot flere hoster, det viste bare korrekt mot sider som jeg hadde 35+ms til.

 

Du kan ikkemodifisere skriptet til å bruke en bedre klokke da? En som teller CPU-tid i stedet for å bruke systemklokke elns...

 

Vanlig systemklokke i en pc har rundt 15-16ms oppløsning, så 0-15-0-15... resultatet er ikke så veldig rart hvis det er den som brukes.

Endret av MailMan13
Lenke til kommentar
Så testet jeg med de scriptene. Det resulterte i 0.0ms, 15ms, 0.0ms, 15ms... etc.. Så det var dårlig! Testet mot flere hoster, det viste bare korrekt mot sider som jeg hadde 35+ms til.

 

Du kan ikke modifisere skriptet til å bruke en bedre klokke da? En som teller CPU-tid i stedet for å bruke systemklokke elns...

 

Vanlig systemklokke i en pc har rundt 15-16ms oppfriskning, så 0-15-0-15... resultatet er ikke så veldig rart hvis det er den som brukes.

 

Joda, det finnes noen alternativer, nå som jeg vet hvorfor. Jeg tør å påstå at en kan benytte: time.clock(), som henter tiden på den måten du spessifiserer. Men, den er "treg" å kalle. Hvor den da bruker opp til 2ms, så det må vel trekkes fra ~2ms på output.. dette må jeg bare se ann, og teste.

 

Disse scriptene som ble vist til, vil fungere bedre på linux-systemer, hvor oppfriskningene pr. sekund er høyere. Det er ikke feil i selve python-pakken.

Endret av tROOP4H
Lenke til kommentar

En alternativ løsning hvor man ikke bruker subprocess,bruker timeit og Httplib2

Som vist her.

http://fitzgeraldsteele.wordpress.com/2009/01/15/simple-web-response-time-testing-with-python/

 

Jeg lagde en test med matplotlib for gøy.

import timeit
import time
import matplotlib.pyplot as plot

# Request the page 20 times, time the response time
t = timeit.Timer("h.request('http://www.google.no/',headers={'cache-control':'no-cache'})", "from httplib2 import Http; h=Http()")
ping_list = t.repeat(20,1)

ping = []
for item in ping_list:
   ping.append(item)

plot.xlabel('Seconds')
plot.ylabel('Ping')
plot.title('Ping Over Time')

#Set the axis, and the horizontal tick marks
plot.axis([1, 2, 0, 1])
plot.xticks(range(1, 20))

#actually do the plotting
# The [None], along with the setup let you not have 0 seconds
plot.plot([None] + ping)
plot.show()

pingl.jpg

Synes dette var en artig bruk av timeit som jeg har brukt mye.

Kan ta litt om timeit og den mere vanlige bruken av den.

Hvilken kode/algoritme er rasket?

Dette er spørsmålet man stiller seg mange ganger,koden under er for rask til og kjøre en gang.

#ordinary loop
l = []
for i in xrange(10):
   l.append(i*2)
print l

#Python list comprehension
l = [i*2 for i in xrange(10)]
prin l

Her kommer timeit inn i bildet.

Vi kjører koden 10000000 ganger og timeit gir ut en gjennomsnitt tid.

import timeit

ol = '''
l = []
for i in xrange(10):
   l.append(i*2)
'''

lc = '''
l = [i*2 for i in xrange(10)]
'''

print timeit.Timer(stmt=ol).timeit(number=10000000)
#ol(ordinary loop) time was 12.1718016571
#lc(list comprehension) time was 7.78384060041

Så list comprehension er litt raskere enn en vanlig loop.

Endret av SNIPPSAT
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...