Home > Back-end >  "Test Failed: unsupported operand type(s) for : 'int' and 'tuple'"
"Test Failed: unsupported operand type(s) for : 'int' and 'tuple'"

Time:12-11

i keep having a problem in my code coming back as Test Failed: unsupported operand type(s) for : 'int' and 'tuple'.

i am a super beginner who is not very good at coding, so i cannot figure out what the issue is.

here is the full code.

i am making a simple icmp pinger program.

thanks everyone for your help!!! (this is my first question here so please let me know if i need to edit anything)

from socket import *
import os
import sys
import struct
import time
import select
import statistics
import binascii

# Should use stdev

ICMP_ECHO_REQUEST = 8


def checksum(string):
   csum = 0
   countTo = (len(string) // 2) * 2
   count = 0

   while count < countTo:
       thisVal = (string[count   1]) * 256   (string[count])
       csum  = thisVal
       csum &= 0xffffffff
       count  = 2

   if countTo < len(string):
       csum  = (string[len(string) - 1])
       csum &= 0xffffffff

   csum = (csum >> 16)   (csum & 0xffff)
   csum = csum   (csum >> 16)
   answer = ~csum
   answer = answer & 0xffff
   answer = answer >> 8 | (answer << 8 & 0xff00)
   return answer



def receiveOnePing(mySocket, ID, timeout, destAddr):
   timeLeft = timeout

   while 1:
       startedSelect = time.time()
       whatReady = select.select([mySocket], [], [], timeLeft)
       howLongInSelect = (time.time() - startedSelect)
       if whatReady[0] == []:  # Timeout
           return "Request timed out."

       timeReceived = time.time()
       recPacket, addr = mySocket.recvfrom(1024)

       # Fetch the ICMP header from the IP packet

       header = recPacket[20:28]
       type, code, checksum, packID, seqNo = struct.unpack("bbHHh", header)
       if type == 0 and packID == ID:
          bytesInDouble = struct.calcsize("d")
          timeSent = struct.unpack("d", recPacket[28:28   bytesInDouble])[0]
          ttls = struct.unpack("c", recPacket[8:9])[0]  
          rtt = timeReceived - timeSent
          return (rtt, ttls)

       timeLeft = timeLeft - howLongInSelect
       if timeLeft <= 0:
           return "Request timed out."


def sendOnePing(mySocket, destAddr, ID):
   # Header is type (8), code (8), checksum (16), id (16), sequence (16)

   myChecksum = 0
   # Make a dummy header with a 0 checksum
   # struct -- Interpret strings as packed binary data
   header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
   data = struct.pack("d", time.time())
   # Calculate the checksum on the data and the dummy header.
   myChecksum = checksum(header   data)

   # Get the right checksum, and put in the header

   if sys.platform == 'darwin':
       # Convert 16-bit integers from host to network  byte order
       myChecksum = htons(myChecksum) & 0xffff
   else:
       myChecksum = htons(myChecksum)


   header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
   packet = header   data

   mySocket.sendto(packet, (destAddr, 1))  # AF_INET address must be tuple, not str


   # Both LISTS and TUPLES consist of a number of objects
   # which can be referenced by their position number within the object.

def doOnePing(destAddr, timeout):
   icmp = getprotobyname("icmp")


   # SOCK_RAW is a powerful socket type. For more details:   http://sockraw.org/papers/sock_raw
   mySocket = socket(AF_INET, SOCK_RAW, icmp)

   myID = os.getpid() & 0xFFFF  # Return the current process i
   sendOnePing(mySocket, destAddr, myID)
   delay = receiveOnePing(mySocket, myID, timeout, destAddr)
   mySocket.close()
   return delay


def ping(host, timeout=1):
  # timeout=1 means: If one second goes by without a reply from the server,      # the client assumes that either the client's ping or the server's pong is lost
   dest = gethostbyname(host)
  # print("Pinging "   dest   " using Python:")
  # print("")
  # Calculate vars values and return them
   count = 0
   val = []
  # Send ping requests to a server separated by approximately one second
   for i in range(0,4):
       delay = doOnePing(dest, timeout)
       val.append(delay)
      # print(delay)
       time.sleep(1)  # one second
         
   if len(val) > 0:      
       packet_min = min(val) * 1000
       packet_avg = sum(val) / len(val) * 1000
       packet_max = max(val) * 1000
       stdev_var =  list(val) * 1000
       vars = [str(round(packet_min, 2)), str(round(packet_avg, 2)), str(round(packet_max, 2)),str(round(stdev(stdev_var), 2))]
   else:
        vars = ['0', '0.0', '0', '0.0']
   return vars

if __name__ == '__main__':
   ping("google.co.il")

CodePudding user response:

You have return (rtt, ttls) in function receiveOnePing and then you return the same tuple from function doOnePing. After that, you append this tuple to list and are trying to sum this list of tuples. This leads to the error you mentioned. You need val.append(delay[0]) in ping function (line 122).

You also use undefined function stdev. Should be statistics.stdev.

Please note that your script will crash in case of timeout because you return a string in this. Also the code is runnable only by root.

UPD Below is fixed code.

rom socket import *
import os
import sys
import struct
import time
import select
import statistics
import binascii

# Should use stdev

ICMP_ECHO_REQUEST = 8


def checksum(string):
   csum = 0
   countTo = (len(string) // 2) * 2
   count = 0

   while count < countTo:
       thisVal = (string[count   1]) * 256   (string[count])
       csum  = thisVal
       csum &= 0xffffffff
       count  = 2

   if countTo < len(string):
       csum  = (string[len(string) - 1])
       csum &= 0xffffffff

   csum = (csum >> 16)   (csum & 0xffff)
   csum = csum   (csum >> 16)
   answer = ~csum
   answer = answer & 0xffff
   answer = answer >> 8 | (answer << 8 & 0xff00)
   return answer



def receiveOnePing(mySocket, ID, timeout, destAddr):
   timeLeft = timeout

   while 1:
       startedSelect = time.time()
       whatReady = select.select([mySocket], [], [], timeLeft)
       howLongInSelect = (time.time() - startedSelect)
       if whatReady[0] == []:  # Timeout
           return "Request timed out."

       timeReceived = time.time()
       recPacket, addr = mySocket.recvfrom(1024)

       # Fetch the ICMP header from the IP packet

       header = recPacket[20:28]
       type, code, checksum, packID, seqNo = struct.unpack("bbHHh", header)
       if type == 0 and packID == ID:
          bytesInDouble = struct.calcsize("d")
          timeSent = struct.unpack("d", recPacket[28:28   bytesInDouble])[0]
          ttls = struct.unpack("c", recPacket[8:9])[0]  
          rtt = timeReceived - timeSent
          return (rtt, ttls)

       timeLeft = timeLeft - howLongInSelect
       if timeLeft <= 0:
           return "Request timed out."


def sendOnePing(mySocket, destAddr, ID):
   # Header is type (8), code (8), checksum (16), id (16), sequence (16)

   myChecksum = 0
   # Make a dummy header with a 0 checksum
   # struct -- Interpret strings as packed binary data
   header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
   data = struct.pack("d", time.time())
   # Calculate the checksum on the data and the dummy header.
   myChecksum = checksum(header   data)

   # Get the right checksum, and put in the header

   if sys.platform == 'darwin':
       # Convert 16-bit integers from host to network  byte order
       myChecksum = htons(myChecksum) & 0xffff
   else:
       myChecksum = htons(myChecksum)


   header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
   packet = header   data

   mySocket.sendto(packet, (destAddr, 1))  # AF_INET address must be tuple, not str


   # Both LISTS and TUPLES consist of a number of objects
   # which can be referenced by their position number within the object.

def doOnePing(destAddr, timeout):
   icmp = getprotobyname("icmp")


   # SOCK_RAW is a powerful socket type. For more details:   http://sockraw.org/papers/sock_raw
   mySocket = socket(AF_INET, SOCK_RAW, icmp)

   myID = os.getpid() & 0xFFFF  # Return the current process i
   sendOnePing(mySocket, destAddr, myID)
   delay = receiveOnePing(mySocket, myID, timeout, destAddr)
   mySocket.close()
   return delay


def ping(host, timeout=1):
  # timeout=1 means: If one second goes by without a reply from the server,      # the client assumes that either the client's ping or the server's pong is lost
   dest = gethostbyname(host)
  # print("Pinging "   dest   " using Python:")
  # print("")
  # Calculate vars values and return them
   count = 0
   val = []
  # Send ping requests to a server separated by approximately one second
   for i in range(0,4):
       delay = doOnePing(dest, timeout)
       val.append(delay[0])
      # print(delay)
       time.sleep(1)  # one second
         
   print(val)
   if len(val) > 0:      
       packet_min = min(val) * 1000
       packet_avg = sum(val) / len(val) * 1000
       packet_max = max(val) * 1000
       stdev_var =  list(val) * 1000
       vars = [str(round(packet_min, 2)), str(round(packet_avg, 2)), str(round(packet_max, 2)),str(round(statistics.stdev(stdev_var), 2))]
   else:
        vars = ['0', '0.0', '0', '0.0']
   return vars

if __name__ == '__main__':
   ping("google.co.il")

>sudo python3 ping.py
[0.0778355598449707, 0.07866811752319336, 0.07798004150390625, 0.07628297805786133]

CodePudding user response:

The error occurs in this line:

packet_avg = sum(val) / len(val) * 1000

Therefore val is suspect. Follow the logic back through doOnePing to receiveOnePing and you will find that function does not return suitable types.

CodePudding user response:

You have a few issues. What I can see:

you are trying to checksum but in python, using an index returns a string, not a character, so this generates a string, not a number:

thisVal = (string[count   1]) * 256   (string[count])

What you probably want in this case is:

thisVal = ord(string[count   1]) * 256   ord(string[count])

and also on this line:

       csum  = (string[len(string) - 1])

to

       csum  = ord(string[len(string) - 1])

Then, you are putting tuples and possibly strings into your val array. You need to decide how you want to handle the errors/time out of the ping. You could just ignore them for now:

   for i in range(0,4):
       delay = doOnePing(dest, timeout)
       if isinstance(delay, tuple):
           val.append(delay[0])
       time.sleep(1)  # one second

That will only add if you received a tuple, and only add the first member of the tuple, which appears to be the delay you want.

  • Related