Cryo
Cryo

Reputation: 63

Python switch function

I've been trying to write a simple Port Scanner using a simple switch function built with if. I've already searched here for a proper solution on how to make the switch function as usable as in C++ or similliar. I found the problem already being discussed on here Replacements for switch statement in Python? and i've tried a few of these approaches but haven't had any luck so far making it run properly. Whatever method i picked from the link i always get a syntax error on the second switch case like this :

  File "/home/h4v0kkx0008c/Desktop/Sources/setup/PortScannerV1.py", line 44
if case(2):
          ^
SyntaxError: invalid syntax

What might be the problem here?

This is the full code i wrote so far :

from socket import *
import time, socket, os, sys, string, argparse, logging, math

n = raw_input("Choose Port range: \n(1)Standard Ports: 0 - 1025\n(2)Middle Range: 1025 - 5000\n(3)Higher Range: 5000 - 49151\n(4)Highest Range: 49151 - 65535\n(5)All Ports: 0 - 65535\n(6)Custom ")

class switch(object):
    value = None
    def __new__(class_, value):
        class_.value = value
        return True

def case(*args):
    return any((arg == switch.value for arg in args))


while switch(n):



    if case(1):
        print"Your choice is: Standard Ports"
        target= raw_input("Please specify Host or Ip to scan: ")
        targetIP = gethostbyname(target)
        print 'Starting scan on host ', targetIP
        for i in range(0, 1025):
            s = socket(AF_INET, SOCK_STREAM)
            result = s.connect_ex((targetIP, i)


    if case(2):
        print"Your choice is: Middle Range"
        target= raw_input("Please specify Host or Ip to scan: ")
        targetIP = gethostbyname(target)
        print 'Starting scan on host ', targetIP
        for i in range(1025, 5000):
            s = socket(AF_INET, SOCK_STREAM)
            result = s.connect_ex((targetIP, i)
        break

    if case(3):
        print"Your choice is: Higher Range"
        target= raw_input("Please specify Host or Ip to scan: ")
        targetIP = gethostbyname(target)
        print 'Starting scan on host ', targetIP
        for i in range(500, 49151):
            s = socket(AF_INET, SOCK_STREAM)
            result = s.connect_ex((targetIP, i)
        break

    if case(4):
        print"Your choice is: Highest Range"
        target= raw_input("Please specify Host or Ip to scan: ")
        targetIP = gethostbyname(target)
        print 'Starting scan on host ', targetIP
        for i in range(49151, 65535):
            s = socket(AF_INET, SOCK_STREAM)
            result = s.connect_ex((targetIP, i)
        break

    if case(5):
        print"Your choice is: All Ports"
        target= raw_input("Please specify Host or Ip to scan: ")
        targetIP = gethostbyname(target)
        print 'Starting scan on host ', targetIP
        for i in range(0, 65535):
            s = socket(AF_INET, SOCK_STREAM)
            result = s.connect_ex((targetIP, i)
        break

    if case(6):
        print"Your choice is: Custom"
        target= raw_input("Please specify Host or Ip to scan: ")
        targetIP = gethostbyname(target)
        print 'Starting scan on host ', targetIP
        startPort= raw_input("Specify starting Port:")
        endPort= raw_input("Specify end Port:")
        for i in range(startPort, endPort):
            s = socket(AF_INET, SOCK_STREAM)
            result = s.connect_ex((targetIP, i)
        break

Upvotes: 2

Views: 7691

Answers (3)

Robson
Robson

Reputation: 823

In Python 3.10 there will be a new syntax called "Structural Pattern Matching" or match/case. This is how it looks in its generic form:

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>

Here is a simple example:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the Internet"

Links:

Upvotes: 1

nigel222
nigel222

Reputation: 8192

If you need to share a set of local variables between the blocks of code in a case-equivalent statement, then a dict of functions may not be the right answer. At the very least you'll have to pass a context entity to all of the functions. Or turn them into class methods with an __init__() to initialize them and store the context in self.whatever

The simpler way is just to use

if switchvar == value1: 
   ... 
elif switchvar==value2:
   ... 
elif # as many more as you need

else: #default
   ... 

This differs from a case statement only in that you can't flow off the end of one block into the next (whereas with functions, you can call then from within other ones). Note that in languages with a case statement, flowing off the end of one block in a case statement into the next is frowned on if not heavily commented. It's commonly a bug, though occasionally useful.

Note the Pythonic if variable in [value1, value2, value3, ...]: is the equivalent of a multiplicity of case labels for value1, value2, ... at the top of the same block.

Upvotes: 1

hspandher
hspandher

Reputation: 16733

The way you are trying to solve this problem does not seems pythonic. Since switch statements don't exist in python, you can simulate switch like behaviour using dictionaries, since functions and classes are first class objects in python.

def func1():
    # do some operation

def func2():
    # some other operation

def default_func():
    # some default action

options = {
    '1': func1,
    '2': func2,
    'default': default_func
}

value = raw_input('enter a number')

result = options.get(int(value), options.get('default'))()

If your functions are simple enough, you can definitely use lambdas for values, which would be definitely be more concise.

Upvotes: 4

Related Questions