Python says global name not defined - python

This is the code for p2p based on sockets that I am working on.
Whenever I try to execute this I get global name not defined error.
import socket
import os.path
import sys
import urlparse
import threading
class Node:
def startlisten(sock):
sock.listen(6)
while True:
c,addr = sock.accept()
print "Client connected all set to go : "+str(addr)
thread1 = threading(target=retrfile,args=(c,))
thread1.start()
def __init__(self):
self.port=raw_input("Enter the port: ")
self.shareddir=raw_input("Enter the name of the folder you want to share: ")
self.sysname=raw_input("Enter your desired nick name: ")
self.known=set()
self.s=socket.socket()
host = socket.gethostname()
port = int(self.port)
print host,port
self.s.bind((host,port))
t=threading.Thread(target=startlisten,args =(self.s,))
t.start()
def retrfile(sock):
code,filename = sock.recv(1024)
if code == 0:
if os.pathisfile(os.path.join("D:\\Sankalp0203\\",filename)):
sock.send("OK",str(os.path.getsize(filename)))
userResponse = sock.recv(1024)
if userResponse == 'Y':
with open(filename,'rb') as f:
bytestoread = f.read(1024)
sock.send(1024)
while bytestoread != "":
bytestoread = f.read(1024)
sock.send(byestoread)
def _hello(self,other):
self.known.add(other)
def _broadcast(self,query,history):
for other in self.known.copy():
if other in history:
continue
try:
name = urlparse(other)[1]
parts=name.split(":")
port = int(parts[-1])
host = "http://"+parts[0]
self.s.connect((host,port))
self.s.send(0,query)
code , size = s.recv(1024)
if code == "OK":
inp = raw_input("File Exists and filesize : "+str(size)+" download? y/n: ")
if inp == Y:
self.s.send(Y)
write(self.s,size)
return code , size,
except:
self.known.remove(other)
return FAIL,EMPTY
def write(sock1,size):
f = open('new'+filename,'wb')
data = sock1.recv(1024)
totalrecv = len(data)
f.write(data)
while(totalrecv < size):
data = sock1.recv(1024)
f.write(data)
totalrecv+=len(data)
def Main():
n=Node()
num=3
while(num):
input = (int)(raw_input("Enter 1 for fetch and 2 to sit idle and 3 to introduce to new peer"))
if(input == 1):
filename = raw_input("Enter the name of the file")
n.query(filename)
if(input == 3):
frnd =raw_input("Enter the url of the friend socket")
n._hello(frnd)
if __name__=='__main__':
Main()
When I execute this i get the following error saying global name not defined pls help
Traceback (most recent call last):
File "D:/Sankalp0203/P2Per.py", line 101, in <module>
Main()
File "D:/Sankalp0203/P2Per.py", line 89, in Main
n=Node()
File "D:/Sankalp0203/P2Per.py", line 28, in __init__
t=threading.Thread(target=startlisten,args =(self.s,))
NameError: global name 'startlisten' is not defined

It's saying that startlisten is not defined because global name startlisten is not defined. There is no global function called startlisten. The method you created is under the Node class. You missed the self. The right way to do it would be:
t=threading.Thread(target=self.startlisten,args =(self.s,))

Related

python thread waits for input before it prints

I'm writing a socket communication program, I have a main thread, and another thread trying to sock.recv()
when it does recieve bytes, it works as it needs, it goes to the right function, which at the end prints, and then the thread listens again to bytes (as wanted).
the problem is that the program won't print until I press enter...
if it matters i'm getting input at the same time in the main thread but it shouldn't matter.
note - the bytes are sent like this:
int (4 bytes) - msg type (string to print is 2)
int (4 bytes) - length of text to print
string ( bytes) - actual text
full code:
import socket
import time
import struct
import threading
import sys
PORT = 54321
def try_to_connect(ip):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
socket.IPPROTO_TCP)
sock.settimeout(1)
try:
sock.connect((ip, PORT))
return sock
except:
return False
def text_parse(text, msg_id):
byte_text = bytes(text, "utf-8")
return struct.pack("II%ds" % len(byte_text), msg_id, len(byte_text), byte_text)
def main(sock):
global file_name
print("connected succefuly. to run a command, write $<command> (no space)\nto request a file, enter file path.\nto exit this program enter exit.")
inputed_text = ''
while True:
inputed_text = input()
if inputed_text == '':
pass
elif inputed_text == "exit":
return
elif inputed_text[0] == "$":
sock.send(text_parse(inputed_text[1:], 0))
else:
file_name = inputed_text
sock.send(text_parse(inputed_text, 1))
def print_string(message, msg_len):
text = struct.unpack("%ds" % msg_len, message)[0].decode("utf-8")
sys.stdout.write(text)
sys.stdout.flush()
def copy_file(message):
global file_name
final_file = open(file_name, "wb")
final_file.write(message)
final_file.close()
def recieve_loop(sock):
while True:
try:
header = sock.recv(8)
if not header: break
msg_type = struct.unpack("I", header[:4])[0]
msg_len = struct.unpack("I", header[4:8])[0]
print(msg_type)
print(msg_len)
message = sock.recv(msg_len)
if msg_type == 2:
print_string(message, msg_len)
elif msg_type == 3:
copy_file(message)
except socket.timeout:
pass
if __name__ == "__main__":
print("welcome to remote desktop program.\nto connect to your computer, enter it's ip.\nto exit enter exit")
text_input = "b,kjhkf"
while True:
text_input = input()
if text_input == "exit":
exit()
else:
sock = try_to_connect(text_input)
if sock:
socket_recieve_thread = threading.Thread(target = recieve_loop, args = [sock])
socket_recieve_thread.start()
main(sock)
socket_recieve_thread.join()
else:
print("the computer is not online")

Python imports module but doesn't recognize it when i initiate it?

I honestly have no idea why this is happening, I assume due to it not being on stack-exchange it's a very n00by mistake on my part. so here's the error:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
UnboundLocalError: local variable 'socket' referenced before assignment
tcpServer.py
import socket
def Main():
UID = 1001
sockets = []
users = [] ## create usernames list
sessionLimit = input("session Queue Limit: ")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.1.74', 12127))
s.listen(sessionLimit) ## listen for 1 connection at a time
while True:
c, addr = s.accept()
sockets.append(c)
users.append(c.recv(1024).decode('utf-8'))
print("Connection from " + str(addr))
data = c.recv(1024).decode('utf-8') ## recieve 1024 bytes from client at a time, and then decode it into utf-8
if not data:
break
temp == data
temp.split(" ")
if temp[0] == "//": ## check to see if user has sent command
if temp[1] == "msg":
for i in range(len(users)):
if users[i] == temp[2]:
sockets[i].send((" ".join(temp[::2])).encode('utf-8'))
else: ## else, send data to all users. Could just use s.sendall(data.encode('utf-8'))
for socket in sockets:
socket.send(data.encode('utf-8')) ## send to sockets[socket]
##print("From connected user: " + data)
##data = data.upper()
##print("Sending: " + data)
##c.send(data.encode('utf-8'))
## command listening
commands = input("-> ")
commands.split(" ")
if commands[0] == "exit":
c.close() ## close connection
elif commands[0] == "/msg":
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send((" ".join(commands[::1])).encode('utf-8'))
"""
elif commands[0] == "/rename": ## dont implement yet, due to users[] length changing
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send("<server_" + UID + "> rename " + commands[2].encode('utf-8'))
"""
c.close()
if __name__ == "__main__":
Main()
Thanks for any help !
- Jacob
The issue is that you're using the variable name socket in the context of your Main() function when you do the following code block:
for socket in sockets:
socket.send(data.encode('utf-8')) ## send to sockets[socket]
That's causing an naming issue with the socket library. If you change that to:
for sock in sockets:
sock.send(data.encode('utf-8')) ## send to sockets[socket]
It will start to work. I also had to indent your code differently to ensure it was all in the Main() function you set up, and had to ensure the input() was parsed as an int. For reference, here's the full code block working for me:
import socket
def Main():
UID = 1001
sockets = []
users = [] ## create usernames list
sessionLimit = int(input("session Queue Limit: "))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.1.74', 12127))
s.listen(sessionLimit) ## listen for 1 connection at a time
while True:
c, addr = s.accept()
sockets.append(c)
users.append(c.recv(1024).decode('utf-8'))
print("Connection from " + str(addr))
data = c.recv(1024).decode('utf-8') ## recieve 1024 bytes from client at a time, and then decode it into utf-8
if not data:
break
temp == data
temp.split(" ")
if temp[0] == "//": ## check to see if user has sent command
if temp[1] == "msg":
for i in range(len(users)):
if users[i] == temp[2]:
sockets[i].send((" ".join(temp[::2])).encode('utf-8'))
else: ## else, send data to all users. Could just use s.sendall(data.encode('utf-8'))
for sock in sockets:
sock.send(data.encode('utf-8')) ## send to sockets[socket]
##print("From connected user: " + data)
##data = data.upper()
##print("Sending: " + data)
##c.send(data.encode('utf-8'))
## command listening
commands = input("-> ")
commands.split(" ")
if commands[0] == "exit":
c.close() ## close connection
elif commands[0] == "/msg":
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send((" ".join(commands[::1])).encode('utf-8'))
"""
elif commands[0] == "/rename": ## dont implement yet, due to users[] length changing
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send("<server_" + UID + "> rename " + commands[2].encode('utf-8'))
"""
c.close()
if __name__ == "__main__":
Main()

calling a variable from outside the function using python

I have this script that allow the user to enter the file name by an argument and then it updates the file version:
#!/usr/bin/env python
import os
import sys
class versionBumper:
def __init__(self):
self.version = None
self.SavedBefore = ""
self.SavedAfter = ""
def change_version(self, file_to_be_modded, packageVersion):
for line in file_to_be_modded:
if packageVersion in line:
print "VERSION FOUND: ", line
self.VersionNumber = line
elif self.VersionNumber is None:
self.SavedBefore += line
else:
self.SavedAfter += line
file_to_be_modded.close()
print "Version: ", self.VersionNumber
return self.VersionNumber
if __name__ == '__main__':
print "sys.argv[1:]:", sys.argv[0:]
versionBumper123 = versionBumper()
filename = sys.argv[1]
path = "/home/Desktop/Crate/Crate/" + filename + "/build/CMakeLists.txt"
if os.path.exists:
inputFile = open(path, 'r')
else:
print "no match found"
sys.exit()
print "Which version number to bump ?"
print "1) major"
print "2) minor."
print "3) patch."
Choose_version = raw_input("Choose version: ")
if Choose_version == "1":
version = versionBumper123.change_version(inputFile, "_MAJOR ")
elif Choose_version == "2":
version = versionBumper123.change_version(inputFile, "_MINOR ")
elif Choose_version == "3":
version = versionBumper123.change_version(inputFile, "_PATCH ")
else:
print "Invalid input. Exiting gracefully..."
sys.exit()
outputFile = open (path, 'w')
splitted_version_line_substrings = version.split('"')
Version_Name = splitted_version_line_substrings[0]
Version_Number = int(splitted_version_line_substrings[1]) + 1
parenthesis = splitted_version_line_substrings[2]
new_version = (str(Version_Name) + '"'
+ str(Version_Number) + '"'
+ str(parenthesis))
print "new_version: ", new_version
outputFile.write(str(versionBumper123.SavedBefore))
outputFile.write(str(new_version))
outputFile.write(str(versionBumper123.SavedAfter))
But I keep getting this error:
Traceback (most recent call last):
File "untitled.py", line 57, in <module>
splitted_version_line_substrings = version.split('"')
NameError: name 'version' is not defined.
I also tried to define version as a global variable but that also did not work, I can't really figure out how to call version from outside the function it is defined in.
Me thinks that you are dealing with a single instance of your class versionBumper
versionBumper123 = versionBumper()
so I guess that what you want to do with the statement
splitted_version_line_substrings = version.split('"')
should be expressed as
splitted_version_line_substrings = versionBumper123.version.split('"')
Just because you use a single instance of your class, imho you could write simpler code if you don't use a class.

Variable not returning. Referenced before assignment

import os.path
import re
import socket
host = ''
port = 6366
s = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
s.bind ((host, port))
def request ():
print ("What file should I write to?")
file = input ()
thing = os.path.exists (file)
if thing == True:
start = 0
elif file.endswith ('.txt'):
stuff = open (file, "w")
stuff.write ("Requests on what to add to the server. \n")
stuff.close ()
start = 0
else:
start = 1
go = "yes"
list1 = (start, file, go)
return list1
start = 1
while start == 1:
list1 = request ()
(start, file, go) = list1
def loop ():
print ("Listening for requests.")
s.listen (1)
conn, addr = s.accept ()
print ("Connected to {0}".format(addr))
while 1:
want = conn.recv(1024).decode()
if not want:
break
if want == "shutdown":
thingy = "no"
print ("Writing to {0}".format(file))
x = open (file, "a")
x.write (want + "\n")
x.close ()
print ("Done writing to {0}".format(file))
x = open (file, "a")
x.write (format(addr) + "\n")
x.close ()
print ("Disconnecting from {0}".format(addr))
conn.close()
print ("Disconnected from {0}".format(addr))
return thingy
while go == "yes":
go = loop ()
if go == "no":
print ("Shutting down")
This is a server. Whenever I try and return "thingy" on line 50, I get the following error.
Traceback (most recent call last):
File "H:\Python\Server Requests\Listen.py", line 52, in <module>
go = loop ()
File "H:\Python\Server Requests\Listen.py", line 50, in loop
return thingy
UnboundLocalError: local variable 'thingy' referenced before assignment
I don't understand why I'm getting this error. I haven't referenced it outside of that one loop. Is there something I'm missing?
For that error;
def loop ():
print ("Listening for requests.")
thingy=""
s.listen (1)
conn, addr = s.accept ()
print ("Connected to {0}".format(addr))
Just add an empty variable called thingy in function. It should solve your problem.
Try Declaring an Empty Variable and then assign values if it satisfy condition. Your return statement will work.

How to make Python play sound?

I am working on a Python chat script, the client looks like this:
import sys
import util
import thread
import socket
class ClientSocket():
rbufsize = -1
wbufsize = 0
def __init__(self, address, nickname=''):
if type(address) == type(()) and type(address[0]) == type('') and
type(address[1])== type(1):
pass
else:
print ('Address is of incorrect type. \n' +
'Must be (serverHost (str), serverPort (int)).')
sys.exit(1)
if nickname:
self.changeNick(nickname)
else:
self.changeNick(raw_input('Nickname: '))
self.prompt_on = False
self.address = address
def connect(self):
self.connection=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.connection.connect(self.address)
self.rfile = self.connection.makefile('rb', self.rbufsize)
self.wfile = self.connection.makefile('wb', self.wbufsize)
self.wfile.write('/nick ' + self.nickname + '\n')
def serve_forever(self):
self.connect()
thread.start_new_thread(self.acceptinput,())
line = ""
while line not in ('/exit','/quit', '/q'):
self.prompt_on = True
line = raw_input(self.prompt)
self.prompt_on = False
if line[:2] == '/n' or line[:5] == '/nick':
self.changeNick(line.split(' ', 1)[1].strip())
self.wfile.write(line + '\n')
self.close()
self.connection.shutdown(socket.SHUT_RDWR)
self.connection.close()
def changeNick(self, newNick):
self.nickname = newNick
self.prompt = self.nickname+': '
self.backspace = '\b' * len(self.prompt)
def acceptinput(self):
while 1:
data = self.rfile.readline().strip()
if data:
self.writedata(data)
if 'Nickname successfully changed to' in data:
self.changeNick(data.split('"')[1])
def writedata(self, data):
if self.prompt_on:
output = data if len(data) >= len(self.prompt) else data + ' '
(len(self.prompt) - len(data))
sys.stdout.write(self.backspace + output + '\n' + self.prompt)
sys.stdout.flush()
else:
print data
def close(self):
if not self.wfile.closed:
self.wfile.flush()
self.wfile.close()
self.rfile.close()
def main():
serverHost = raw_input('Server IP/Hostname: ')
if not serverHost:
serverHost = util.getIP()
else:
serverHost = socket.gethostbyname(serverHost)
serverPort = input('Server Port: ')
address = (serverHost, serverPort)
client = ClientSocket(address)
print 'Connecting to server on %s:%s' % (serverHost, serverPort)
client.serve_forever()
if __name__ == '__main__':
main()
I was wondering if there would be a way to play a sound every time a new messages. Possible using winsound ? (http://stackoverflow.com/questions/307305/play-a-sound-with-python)
Thanks:)
I am pleasantly surprised that winsound is standard library module. Just note that is only available on Windows.
What happens in your writa_data function you do this after the flush. Does this get your desired effect?
import winsound
# Play Windows exit sound.
winsound.PlaySound("SystemExit", winsound.SND_ALIAS)
Okay, figured it out !!! Thanks for the help! :DDD
You add the winsound.PlaySound("SystemExit", winsound.SND_ALIAS) on line 101, above the sys.stdout.write(self.backspace + output + '\n' + self.prompt). Now whenever a new message comes through, it plays a 'ding!'. If you wanted to use a custom .wav sound from the same directory the script is running from, add a winsound.PlaySound("ding.wav", winsound.SND_FILENAME) on line #101 instead. Enjoy!

Categories