title: converting python 2 code to python 3
body: <p>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: <a href="http://code.activestate.com/recipes/483730-port-forwarding/" rel="nofollow noreferrer">http://code.activestate.com/recipes/483730-port-forwarding/</a></p>
  
  <pre><code>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')
  </code></pre>
  
  <p>Here is what I have:</p>
  
  <pre><code>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 &lt;ctrl-c&gt;
      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')
  </code></pre>
  
  <p>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?</p>
  
  <p>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 <a href="https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists" rel="nofollow noreferrer">https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists</a></p>
  
  <p>But I don't understand why passing the settings list without the asterisk doesn't work.</p>
  
  <p>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.</p>