Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

converting python 2 code to python 3

I am trying to convert the following code written in python 2 to python 3. This python code does TCP port forwarding. It is from this page: http://code.activestate.com/recipes/483730-port-forwarding/

import socket
import sys
import thread

def main(setup, error):
    sys.stderr = file(error, 'a')
    for settings in parse(setup):
        thread.start_new_thread(server, settings)
    lock = thread.allocate_lock()
    lock.acquire()
    lock.acquire()

def parse(setup):
    settings = list()
    for line in file(setup):
        parts = line.split()
        settings.append((parts[0], int(parts[1]), int(parts[2])))
    return settings

def server(*settings):
    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        dock_socket.bind(('', settings[2]))
        dock_socket.listen(5)
        while True:
            client_socket = dock_socket.accept()[0]
            server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server_socket.connect((settings[0], settings[1]))
            thread.start_new_thread(forward, (client_socket, server_socket))
            thread.start_new_thread(forward, (server_socket, client_socket))
    finally:
        thread.start_new_thread(server, settings)

def forward(source, destination):
    string = ' '
    while string:
        string = source.recv(1024)
        if string:
            destination.sendall(string)
        else:
            source.shutdown(socket.SHUT_RD)
            destination.shutdown(socket.SHUT_WR)

if __name__ == '__main__':
    main('proxy.ini', 'error.log')

Here is what I have:

import socket
import sys
import threading
import time

def main(setup, error):
    # open file for error messages
    sys.stderr = open(error, 'a')
    # read settings for port forwarding

    threads = []

    for settings in parse(setup):
        #thread.start_new_thread(server, settings)
        t = threading.Thread(target=server, args=(settings))
        t.start()
        threads.append(t)

    for t in threads:
        t.join()

    # wait for <ctrl-c>
    while True:
        time.sleep(60)

def parse(setup):
    settings = list()
    file = open(setup)

    for line in iter(file):
        parts = line.split()
        settings.append((int(parts[0]), parts[1], int(parts[2])))

    return settings

def server(*settings):

    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        dock_socket.bind(('', settings[0]))
        dock_socket.listen(5)
        while True:
            client_socket = dock_socket.accept()[0]
            server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server_socket.connect((settings[1], settings[2]))

            Thread1 = threading.Thread(target=forward, args=(client_socket, server_socket))
            Thread1.start()

            Thread2 = threading.Thread(target=forward, args=(server_socket, client_socket))
            Thread2.start()

    finally:
        thread = threading.Thread(targer=server, args=settings)
        thread.start()

def forward(source, destination):
    string = ' '
    while string:
        string = source.recv(1024)
        if string:
            destination.sendall(string)
        else:
            source.shutdown(socket.SHUT_RD)
            destination.shutdown(socket.SHUT_WR)

if __name__ == '__main__':
    main('port-forward.config', 'error.log')

The python 3 version does seem to work. But I am not fully certain if it is written correctly. I am unclear about the threads portion of the code. The python 2 version is using the thread module while the python 3 version is using the threading module. Looking at the python 2 version, it uses locks in the main function. Do I need to use locks in the python 3 version? Another question is, should I be joining the two threads (thread 1 and thread 2) in the server function in the python 3 code?

Another question I have regardless of python version is the argument to the server function. I understand that the "settings" variable refers to a list. Why does there need to be a asterisk preceding the "settings" argument? I did take a look at the following page in python documentation https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists

But I don't understand why passing the settings list without the asterisk doesn't work.

Another question I have is regarding the thread locks in the python 2 code. Why is the lock being acquired twice? I tried removing one of the locks and the program ends immediately after being started.

like image 863
user695752 Avatar asked Oct 17 '25 17:10

user695752


1 Answers

You could have saved yourself some work by using the commandline tool 2to3 to convert the code to Python 3, like this (from the bash or Windows command line):

2to3 -w myscript.py

But let's answer your actual question: Why the star in the definition

def server(*settings):
    ...

The function thread.start_new_thread will in effect launch your server() function like this:

server(arg1, arg2, arg3)

where arg1, arg2 etc. come from the second argument of start_new_thread. The declaration def server(*settings) collects these arguments back into a single list, settings, which your function goes on to use. If you write def server(settings) (no star), your function is declared to take one argument but will be called with several.

like image 91
alexis Avatar answered Oct 19 '25 05:10

alexis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!