본문 바로가기

프로그래밍/Python

Programmability for Networker : Part 3

 


 

이번 포스팅은 지난 포스팅에 이어서 실제 Python 예제를 통해서 보려고 합니다.

기본 내용은 지난 포스팅과 이어지게 됩니다.  예제 소스는 기존 포스팅과 함께 왔다리 갔다리

하기 힘드실 듯하여... 해당 예제 포스팅이 끝날 때까지 계속 포함할 예정입니다. 

혹시 기존 포스팅을 보지 못하신 분은 반드시!

 

Python for Networker : Part 2

 

을 보고 오셔야 합니다.

 

본 내용에 사용된 에제는 아래에서 볼 수 있습니다.

[ 예제 링크 ] https://github.com/datacenter/who-moved-my-cli

 

※ 본 내용의 진행은 Nexus 5548 6.0(2)N2(4) 기준입니다.

 

 


 

pingrange.py

import re

from cisco import cli

from argparse import ArgumentParser

def expandrange(rangefunc):

    hosts = []

    octets = rangefunc.split('.')

    for i,octet in enumerate(octets):

        if '-' in octet:

            octetrange = octet.split('-')

            for digit in range(int(octetrange[0]), int(octetrange[1])+1):

                ip = '.'.join(octets[:i] + [str(digit)] + octets[i+1:])

                hosts += expandrange(ip)

            break

    else:

        hosts.append(rangefunc)

    return hosts

 

parser = ArgumentParser('pingrange')

parser.add_argument('ip', help='IP range to ping, e.g., 10.1.0-1.0-255 will expand to 10.1.0.0/23')

parser.add_argument('options', nargs='*', help='Options to pass to ping', default=['count 1'])

args = parser.parse_args()

targets = expandrange(args.ip)

for ip in targets:

    tupleping  = cli('ping %s %s' % (ip, ' '.join(args.options)))

    strping = str(tupleping)

    m = re.search('([0-9\.]+)% packet loss',strping )

    print('%s - %s' % (ip, 'UP' if float(m.group(1)) == 0.0 else 'DOWN'))

 

❖ python 코드 실행 순서

  -  Active한 대화명 프롬프트 모드에서의 Python 실행이 아닌, Python 스크립트 코드를 보면서 어떻게 실행이 되는지

    혹시라도 헛갈리실 수 있을 듯 싶어서, 간단하게 위의 코드를 보면서 어떤 순서로 실행되는 보려고 합니다.

  - 우선 모든 코드는 제일 위에서부터 차례대로 진행이 되기 때문에 지난 Part 2에서 얘기된 필요한 Python 모듈을 먼저 Import

    하는 것으로 코드가 시작이 됩니다. 실제 아래 정의되는 실행부분에서 해당 모듈의 내용을 사용해야 하기 때문에 Python 모듈을

    Import하는 것이 당연히 제일 먼저 선언되어야 할 것입니다.

  - 그리고나서는 순서대로 실행이 되어야 하나, 위에서 보면 def 키워드로 expandrange() 함수가 선언되어 있습니다.

    함수는 바로 실행되지는 않기 때문에 expandrange() 함수 영역까지 (상단에서 보면 return host 부분)는 실제 바로 실행되지는

    않습니다.

  - 함수 선언부가 지난 이후에 일반 실행 코드가 순서대로 실행이 되게 됩니다.

  - 그리고 targets = expandrange(args.ip)에서 상단에 선언한 함수를 호출을 하게 됩니다. 그러면 당연히 Def로 선언한 함수

    선언부의 첫 줄부터 실행을 하게 되고, return host 부분까지 실행 후에는 해당 함수를 호출했던 라인으로 복귀를 하게 됩니다.

  - 그 다음에는 for문을 순환한 이후에 프로그램이 종료하게 됩니다.

  - 별다른 내용은 아니긴 하지만, 코드를 보면서 def나 class로(앞으로 다뤄질) 지정된 부분은 그 해당 라인에서 바로 실행이 아니라

    해당 내용을 사용하기 위한 선언부이기 때문에 실행 해당 내용이 실행되는 시점은 아래 실행 코드에서 해당 선언부를 호출하는

    경우가 되게 됩니다. 

 

 


 

 

 

python 문자열 다루기

      - Network 장비에서의 Python 사용에 있어서 가장 많이 활용하기 위해서 사용하는 부분이 문자열을 어떻게 다루느냐가 아닐 듯

       싶습니다.  물론 만약에 장비에서 얼마나 많은 종류의 자체 Python 모듈을 제공하느냐에 따라서 이 부분이 달라질 수 있을 듯

       싶지만, 그렇다고 하더라도 문자열을 가지고 활용할 수 있는 방법은 많을 것 같습니다. 이번 포스팅에서는 이런 문자열 다루기에

       대해서 다뤄봅니다. 아래 내용은 위의 코드를 이해하는 데 가장 많이 사용되는 부분이니, 꼭! 중요하게 읽어보셔야 할 것이라~

       생각해봅니다.

  

문자열 선언

   문자열을 선언하는 방법에는

       문자열’ , “문자열” , ‘’’다중라인 문자열‘’’, “””다중 라인 문자열“””

   •’, “ 모두 표기 가능하게 하여, 문자열 안에 를 넣으려고 할 때에는 문자열 안에 기호와 반대로 문자열을 묶어주면 안의

      기호는 문자열 기호가 아니라 단순히 ‘, “ 의 역할만 하게 된다.

       , “Network” ZIGI를 표현하고 싶을 경우에는 로 묶어서 ‘ “Network” ZIGI ‘ 쓰면 된다.

 

문자열 슬라이싱

   문자열[시작Idx:종료Idx-1]   : 문자열을 시작 Index 지점부터, 종료 Index – 1까지 의 문자열을 잘라낸다.

   시작 Index와 종료 Index를 각각 생략하게 되면, 각각 최초 시작 지점/종료 지점을 가리키게 된다.

 

❖ 문자열 연산

   문자열을 ‘+’로 합치는 경우에는 두 문자열 사이에 공백이 없이 합쳐지고, ‘,’로 합치는 경우에는 두 문자열 사이에 공백이

     들어가면서 합쳐지게 된다.

 

❖ 문자열 Formatting

   •print 시에 %s, %c, %d 등으로 지정하여 원하는 데이터 값을 출력 할 수 있다.

   Formatting 코드에 맞춰서 값을 넣어야 하지만, %s로 지정할 경우에는 자동 변환이 되서 들어가게 된다.

   문자열 내에 %를 사용하여 Formatting 시에는 %를 일반 문자로 출력하려면 %%로 써야 출력이 된다.

      하지만, 문자열 내에 % 사용한 Formatting이 없으면 그냥 %만 써도 된다.

   •%숫자s 과 같이 %Formatting 코드 사이에 숫자를 넣으면 해당 크기만큼 공간을 할당해서 출력하게 된다.

       이 때에 숫자를 로 입력하면 해당 공간만큼 할당하여 문자열을 왼쪽 정열하여 출력하게 된다.

  

%s 문자열 (String)

%c 문자 한개(character)

%d 정수 (Integer)

%f 부동소수 (floating-point)

%o 8진수

%x 16진수

%% Literal % (문자 '%s' 자체) 

 

Formatting Example Code

Example Code Result

print "I warn %d won." % 100

print "Americano %d won. Latte %d won" % (3900,4600)

print "My Name is %s" % ("Network ZIGI")

I warn 100 won.

Americano 3900 won. Latte 4600 won

My Name is Network ZIGI

print "%15s %s" % ("Network", "ZIGI")

print "%-15s %s" % ("Network", "ZIGI")

        Network ZIGI

Network         ZIGI

 

문자열 Method

•find(keyword, [start, [end]])   / rfind(keyword, [start, [end]])

     - 문자열에서 Keyword가 위치한 첫 번째(rfind는 뒤에서부터 첫 번째) Index리턴하고, 해당 Keyword가 존재하지 않으면

       ‘-1’을 리턴

•index(keyword, [start, [end]])

     - find() 와 동일한 동작을 하지만, Keyword가 존재하지 않을 경우에 ‘-1’이 아닌 ValueError 예외를 발생.

•join(sequence)

      - sequence 형변수를, Join을 호출한 문자열로 연결해서 리턴하는 메서드이며, split()와 반대의 역할을 하게 됨.

•partition(separator)

      - 문자열을 separator을 나누게 되는 데, separator , separator , separator 뒤의 3개의 Tuple로 리턴.

lstrip([chars])

      - 문자열의 왼쪽을 제거.chars을 지정하지 않으면 공백 문자를 제거.

 

 

Join / Partition / lstrip Example Code

 Join / Partition / lstrip Example Code Result

str1 = '-'

joinstr = str1.join("abc")

print(joinstr)

 a-b-c

str1 = "Network ZIGI Good"

partStr = str1.partition("ZIGI")

print(partStr)

part1 = partStr.__getitem__(2)

print(part1)

part1 = part1.lstrip()

print(part1)

 

('Network ', 'ZIGI', ' Good')

 Good

Good

 

•Split([separator, [maxsplit]])

      - separator로 문자열을 분리하는 것은 Partition과 동일하나, Partition의 경우에는 separator도 함께 리턴되지만,

        split는 해당 separator 기준으로 분리가 되면서 포함되지 않는다.

      - 뒤에 Maxsplit의 값을 주게되면, 앞에서부터 분리되는 개수의 max 값을 지정할 수 있다

Strip([chars])

      - 문자열 양쪽 끝을 잘라내는 데, 별도의 chars를 지정하지 않으면 공백을 제거하고 chars 지정 시에는 해당 문자가 포함된

        모든 내용이 삭제 된다

 

 

Split Example Code

Split Example Code

str1 = "Network ZIGI Good Split Test"

partStr = str1.partition("ZIGI")

print(partStr)

str2 = str1.split()

print(str2)

str3 = str1.split("ZIGI")

print(str3)

str4 = str1.split(' ',2)

print(str4)

 

('Network ', 'ZIGI', ' Good Split Test')

['Network', 'ZIGI', 'Good', 'Split', 'Test']

['Network ', ' Good Split Test']

['Network', 'ZIGI', 'Good Split Test']