2010-12-10 4 views
2
def generate_macs(): 
    for i in xrange(0x000000, 0xFFFFFF + 1): 
     mac = hex(0x000000 + i)[2:].upper() 
     mac = [mac[x:x + 2] for x in range(0, len(mac), 2)] 

     yield ':'.join(mac) 

for mac in generate_macs(): 
    print 'E8:06:88:{0}'.format(mac) 

Ich versuche, eine Liste der MAC-Adressen zwischen E8:06:88:00:00:00 and E8:06:88:FF:FF:FF zu generieren.Python scheint zu sterben, bevor es diese Hex-Werte durchläuft. Wie fest?

Das Programm scheint auf dieser Linie zu sterben:

[email protected]:~$ tail range1.txt 
E8:06:88:44:86:55 

Warum ...? :/

+0

Es stirbt konsequent an der gleichen Stelle? Benötigen Sie nur die einmal erstellte Liste? Was passiert, wenn Sie Ihre XRange nur auf 0x448650 bis 0x44865F ändern? Ist das der genaue Code, den Sie verwenden? – kevpie

+0

Sie haben immer noch nicht gesagt, wofür Sie diese benötigen. Sie wissen, dass die volle Ausgabe in der Nähe von 300 MB sein wird, ja? –

Antwort

0

Die Macs werden nicht in der von Ihnen erwarteten Reihenfolge zurückgegeben. Ich lief nur den Code und bekam folgendes:

furby:playground jonesy$ grep 'FF:FF:FF' macs.txt 
E8:06:88:FF:FF:FF 
+0

Der Generator ergibt die Macs in Reihenfolge (abgesehen von der Frage der führenden Nullen) Ich vermute, dass dies nicht der genaue Code ist, der das Problem verursacht –

0

Können Sie uns sagen, was passiert, wenn es aufhört?

Auch Sie können mehr Glück ersetzen

mac = hex(0x000000 + i)[2:].upper() 

mit

max = "%06X"%i 

es dem führenden Null Problem

+0

Es kommt zu einem bestimmten Punkt und stoppt einfach. Keine Fehler, nur nichts. Ich kann auch nicht ctrl + c entkommen. Ich muss das Terminal töten. – dave

+0

@charles, können Sie uns mehr über die Umwelt erzählen? Welche Python-Version? Laufen Sie auf einem lokalen Rechner? Welches Terminal benutzen Sie? –

+0

Python 2.6.5 auf einer Ubuntu 10.04.1 LiveCD. Mit/bin/bash – dave

6

Zuerst Ihr Generator löst Funktion macht es nicht Ausgabe einen vollständigen MAC Adresse vor der dritten Ziffer; Ich gelöst, dass durch den folgenden Code:

def generate_macs_2(): 
    for a in range(0, 0x100): 
     for b in range(0, 0x100): 
      for c in range(0, 0x100): 
       yield "{0:02X}:{1:02X}:{2:02X}".format(a, b, c) 

for mac in generate_macs_2(): 
    print 'E8:06:88:' + mac 

Es gibt auch die MAC-Adressen in der Reihenfolge von der niedrigsten zur höchsten, in Bezug auf die Zahlenwert, in Großbuchstaben, und ist einfacher zu sehen und auf einen Blick verstehen (MEINER BESCHEIDENEN MEINUNG NACH).

Der Vollständigkeit halber und weil es unten erwähnt wurde, ist hier, wie es mit itertools.product zu tun:

def generate_macs_3(): 
    for item in itertools.product(range(0, 0x100), repeat = 3): 
     yield "{0:02X}:{1:02X}:{2:02X}".format(item[0], item[1], item[2]) 

for mac in generate_macs_3(): 
    print 'E8:06:88:' + mac 

Die Läufe des OP in ~ 40 Sekunden auf meinem System, meine erste läuft in ~ 26 Sekunden Durchschnitt und der zweite (unter Verwendung von itertools) dauert etwa ~ 32 Sekunden.

+0

Dies würde noch besser gemacht werden mit ['itertools.product'] (http://docs.python.org/library/itertools.html#itertools.product) –

+0

Ich bin ziemlich neu in Python, also ich haven ' Ich habe noch keines der Itertools ausprobiert, aber es ist auf meiner Liste. Außerdem scheint diese Version fast 40% schneller zu laufen als die OP-Version ... –

+0

Ah, das ist schön. Bekam es mit 'itertools.product' und das ist cool, obwohl es ungefähr 8 Sekunden langsamer als die geschachtelte for-Schleife oben zu sein scheint. Auch interessant; Ich hätte erwartet, dass es schneller geht. –

2

Michael Trausch hat einige gute Möglichkeiten, um diese zu generieren, aber wenn Sie über Geschwindigkeit besorgt sind, dann ist hier wahrscheinlich so schnell es mit reinem Python getan werden kann, ohne Multiprocessing (die wirklich beschleunigen könnte):

import sys 
def generate_macs(): 
    localf = "E8:06:88:{0:02X}:{1:02X}:{2:02X}\n".format 
    localx = xrange(0,0x100) 
    sys.stdout.writelines([localf(a,b,c) for a in localx \ 
          for b in localx for c in localx]) 

Das dauert auf meinem Computer etwa 53% weniger Zeit als die schnellste Generatorlösung in Michaels Beitrag. Natürlich, wenn Sie nicht über den Speicher verfügen, um sie alle als eine Liste zu erstellen, bevor Sie sie ausschreiben (wie in meinem Code), dann können Sie die Klammern entfernen (die es dann in einen Generatorausdruck machen) und der Code ist nur etwa 39% schneller.

Wie auch immer, Sie müssen wahrscheinlich nicht so oft generieren, so Geschwindigkeit ist nicht sehr wichtig, aber wenn es ist, dann haben Sie es.

0

Ich war von diesem Problem fasziniert und wollte die Generierung beliebiger Bereiche untersuchen. Ich habe festgestellt, dass Hex-Formatierung im Allgemeinen der Flaschenhals und String-Formatierung/Verkettung ist.

Es gibt Möglichkeiten, wie dieser Code weiter optimiert werden könnte. Abgesehen davon wollte ich Dable mit Nachschlagetabellen und bitweisen Operationen.

Diese Lösungen verwenden zur Laufzeit etwa 10 MB RAM. Wenn die Liste wurde unter Verwendung einer Liste Verständnis materialisiert es über 1 GB verwendet und dauert länger ...

Meine beste Lösung bisher berechnet pre hex Codierungen in eine Liste. 2 Hex-Bereiche werden pro Nachschlagetabelle codiert, um den Treffer der Zeichenfolgenformatierung zu vermeiden. Wenn ich versuchte, mehr Hexadezimalziffern in einer Zeichenfolge zu verwenden, wurde die Nachschlagetabelle zu groß und auch das Tool wurde länger generiert, als die Funktionen zum Ausführen benötigten.

Schnellste, weil es etwa halb so viele Saiten

from itertools import product 

def generate_macs(first, last): 
    begin = int(first.replace(':', ''), 16) 
    end = int(last.replace(':', ''), 16) + 1 
    look_co = ['%02X:%02X:' % i for i in product(xrange(0x00, 0x100), repeat=2)] 
    look_ln = ['%02X:%02X\n' % i for i in product(xrange(0x00, 0x100), repeat=2)] 

    return (look_co[i >> 32 & 0xFFFF] + \ 
      look_co[i >> 16 & 0xFFFF] + \ 
      look_ln[i & 0xFFFF] for i in xrange(begin, end)) 

Andere Versionen verwenden Zeichenfolge Formatierung oder 2hexdigit Gruppierungen String verketteten behandelt.

reine Hex Formatierung

def generate_macs(first, last): 
    begin = int(first.replace(':', ''), 16) 
    end = int(last.replace(':', ''), 16) + 1 

    return ('%02X:%02X:%02X:%02X:%02X:%02X\n' % (
       i >> 40 & 0xFF, 
       i >> 32 & 0xFF, 
       i >> 24 & 0xFF, 
       i >> 16 & 0xFF, 
       i >> 8 & 0xFF, 
       i & 0xFF) for i in xrange(begin, end)) 

2Hex Digits pro Lookup-Zeichenfolge concated

def generate_macs(first, last): 
    begin = int(first.replace(':', ''), 16) 
    end = int(last.replace(':', ''), 16) + 1 
    look_co = ['%02X:' % i for i in xrange(0x00, 0x100)] 
    look_ln = ['%02X\n' % i for i in xrange(0x00, 0x100)] 
    return (look_co[i >> 40 & 0xFF] + \ 
      look_co[i >> 32 & 0xFF] + \ 
      look_co[i >> 24 & 0xFF] + \ 
      look_co[i >> 16 & 0xFF] + \ 
      look_co[i >> 8 & 0xFF] + \ 
      look_ln[i & 0xFF] for i in xrange(begin, end)) 

2Hex Digits pro String-Suche

def generate_macs(first, last): 
    begin = int(first.replace(':', ''), 16) 
    end = int(last.replace(':', ''), 16) + 1 
    look_co = ['%02X:' % i for i in xrange(0x00, 0x100)] 
    look_ln = ['%02X\n' % i for i in xrange(0x00, 0x100)] 
    return (''.join((look_co[i >> 40 & 0xFF], 
      look_co[i >> 32 & 0xFF], 
      look_co[i >> 24 & 0xFF], 
      look_co[i >> 16 & 0xFF], 
      look_co[i >> 8 & 0xFF], 
      look_ln[i & 0xFF])) for i in xrange(begin, end)) 
beitreten

-Code verwendet es

f = open('foobar.txt', 'w') 
f.writelines(generate_macs('E8:06:88:00:00:00', 'E8:06:88:FF:FF:FF')) 
f.close() 

Die anderen Lösungen von Justin und Michael sind beide unendlich besser lesbar/wartbar angeboten laufen. Michaels benutzt 4MB oder Ram auf meinem Rechner. Justin verwendet 1 GB mit List Comprehension und nur 4 MB, wenn er durch einen Generator-Ausdruck ersetzt wird (wie er erwähnt hat). Mine 10MB verwenden und läuft etwa zweimal schnell, kostet der Client wahrscheinlich 10 mal so viel und wird in Zukunft weiter.

Die Metriken für die Leistung verwendeten Disk I/O in os/Activity Monitor und Mississippis von x.

EDIT: Neue Gewinner.

Schnellste Diese wirklich schreit und verwendet 4.1MB RAM. Generiert die Ausgabe in 2 Sekunden nach/dev/null.

def generate_macs(): 
    from operator import add 
    from itertools import product 
    heads = [ 'E8:06:88:%02X:%01X' % i for i in product(xrange(0, 0x100), xrange(0, 0x10))] 
    tails = [ '%01X:%02X\n' % i for i in product(xrange(0, 0x10), xrange(0, 0x100))] 
    return starmap(add, product(heads, tails)) 

zweitschnellste fast so schnell wie die oben, wohl besser lesbar. 4,1 MB. Erzeugt Ausgabe nach/dev/null in 3 Sekunden

def generate_macs(): 
    from itertools import product 
    hexs = [':%02X' % h for h in xrange(0, 0x100)] 
    return imap(''.join, product(('E8:06:88',), hexs, hexs, hexs, ('\n',))) 

Fazit

  • Meine letzten Lösungen haben keine Lookup-Tabellen und keine bitweise Operationen.
  • Es gibt interessante Anwendungen für Produkt wie sie von den anderen Plakaten eingeführt.
  • Jedes Mal, wenn Sie implizite Schleifen verwenden und Dinge auf c (wie ich es verstehe) tun können.
  • Formatieren Sie weniger, oft.
Verwandte Themen