linking python to scratch

A forum for general discussion of the Python programming language.

linking python to scratch

Postby dec.stanley » Thu Mar 21, 2013 9:01 pm

I'm starting my GCSE Computing next year and it is on Python. I am using Python 2.7.3 and know all about Tkinter. I found this coding on the internet on how to link python scratch. I know how to use it but my teacher said i can only use it if i understand how it works. Here's the coding:

from array import array
import socket

from Tkinter import Tk
from tkSimpleDialog import askstring
root = Tk()

PORT = 42001
HOST = ''

scratchSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
scratchSock.connect((HOST, PORT))

def sendScratchCommand(cmd):
n = len(cmd)
a = array('c')
a.append(chr((n >> 24) & 0xFF))
a.append(chr((n >> 16) & 0xFF))
a.append(chr((n >> 8) & 0xFF))
a.append(chr(n & 0xFF))
scratchSock.send(a.tostring() + cmd)

while True:
msg = askstring('Scratch Connector', 'Send Broadcast:')
if msg:
sendScratchCommand('broadcast "' + msg + '"')

I have edited it slightly but generally it is the same. The bit I don't understand it the sendScratchCommand(cmd) definition.
can anyone explain it to me?
Posts: 5
Joined: Thu Mar 21, 2013 8:16 pm

Re: linking python to scratch

Postby setrofim » Thu Mar 21, 2013 10:13 pm

Please use [code ] tags when posting code.

This function sends the command that it gets as the argument perpended with it's length as a 32 bit integer to the socket.

Let's break this down:
  • n is the length of the command (it is a Python integer object).
  • a is an array of chars (that's what the 'c' means). An array is sort of like a list, except it occupies a consecutive chuck of memory and it can only contain elements of one type. A char is an 8 bit (or 1 byte) integer.
  • The >> is a bit shift operator. It shifts the binary representation of the left argument (in this case, n) right by the number of bits specified by the right argument (24, the first time it is used). An example will make this clearer:
    Code: Select all
    >>> cmd = 'broadcast "Attack at dawn."'
    >>> n = len(cmd)
    >>> n

    The binary representation of n is
    Code: Select all
    >>> bin(n)

    Now when I shift n right by one bit we get:
    Code: Select all
    >>> bin(n >> 1)

    Notice that the left bit dropped off. Incidentally, this is equivalent to dividing n by 2 (think about it).
  • 0xFF is just an integer expressed in hex. Here it is used as a bit mask. 0xFF is the highest value an 8 bit integer (or char) can have -- it is all ones:
    Code: Select all
    >>> bin(0xFF)
  • The & is the bit-wise AND operator.
  • Taking the above together,
    Code: Select all
    a.append(chr((n >> 24) & 0xFF))

    this shifts n by 24 bits, which get's rid of to the 24 least significant bits of n, AND's it with the 8-bit mask, which has the effect of "trimming" n to an 8 bit value, and converts the resulting value to a char that gets appended onto the array.
  • If you think of n as a 32 bit (or 4 byte) integer (standard int size for x86 systems), then effect of this operation is to append the most significant byte of n to the array. The next line (that shifts n by 16) appends the second most significant byte of n to the array, and so forth.
  • By the time all the appends are done, a contains all four bytes of n as chars.
  • Finally, the array is converted to a string and is prepended to the command, before the entire thing is sent to the socket.
This may seem like a round about way of doing it, but the reason it is necessary is because the length of the command needs to be sent as a 32 byte value. If you simply tried prepending n, you will end up with this:
Code: Select all
"24broadcast 'hello, world'"

The length becomes the two chars '2' and '4', which is only 16 bytes (and their value isn't the actual length (e.g. the value of char '2' is x32, or 50). What actually ends up being sent is
Code: Select all
>>> a.tostring() + command
"\x00\x00\x00\x18broadcast 'hello, world'"

Note that the \x in the string is a special escape sequence to specify the byte value of a (possibly unprintable) character. So '\x00' is a sing char with zero value, not four separate characters.

Incidentally, a more concise way to achieve the same thing would be to use the struct module:
Code: Select all
>>> import struct
>>> struct.pack('>i', n)
Posts: 288
Joined: Mon Mar 04, 2013 7:52 pm

Re: linking python to scratch

Postby micseydel » Fri Mar 22, 2013 2:36 am

You should have read this before posting. Your question isn't about GUIs, and so you should not have included any GUI code in your question.
Due to the reasons discussed here we will be moving to on October 1, 2016.

This forum will be locked down and no one will be able to post/edit/create threads, etc. here from thereafter. Please create an account at the new site to continue discussion.
User avatar
Posts: 3000
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

Re: linking python to scratch

Postby dec.stanley » Fri Mar 22, 2013 6:19 pm

Sorry i just really wanted to find out the answer. What about the chr bit
Posts: 5
Joined: Thu Mar 21, 2013 8:16 pm

Re: linking python to scratch

Postby setrofim » Fri Mar 22, 2013 6:27 pm

dec.stanley wrote:What about the chr bit

Sorry, I didn't explain that properly. chr() converts a Python integer into a char (i.e. a character or an 8 bit/1 byte integer). In order for this to work, the Python integer has to be < 256 (otherwise you get an exception).
Posts: 288
Joined: Mon Mar 04, 2013 7:52 pm

Re: linking python to scratch

Postby dec.stanley » Fri Mar 22, 2013 7:09 pm

Thanks a lot :D
Posts: 5
Joined: Thu Mar 21, 2013 8:16 pm

Return to General Discussions

Who is online

Users browsing this forum: No registered users and 7 guests