2

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
5
  • 2
    s.connect_ex((targetIP, i) you forgot to close a bracket. Commented Aug 27, 2015 at 11:57
  • 1
    By the way, note that your approach is very un-Pythonic. What's wrong with using a series of if n == 1:, elif n == 2:, ...? You can also define an enum to avoid using bare numbers. Commented Aug 27, 2015 at 12:01
  • 1
    The final top-level break in the while loop is also not optional. Currently, this is an infinite loop when none of the cases match. Commented Aug 27, 2015 at 12:01
  • Oh my god, i feel stupid now ^^ thx for the answer (in terms of the bracket) Commented Aug 27, 2015 at 12:01
  • @AndreaCorbellini I had the same error with the if/elif/else statements too, but since it was a bracket problem i surely will rebuild this now to look more pythonic. Commented Aug 27, 2015 at 12:03

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks i'll try this one out. For clarification, func1, func2 ...etc would be the functions and options link the functions to numbers ?
yep... numbers or any other object could be a key in this case, making in much more powerfull approach than switch statements in many languages
1

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.

Comments

1

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:

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.