我有一个客户端 - 服务器应用程序,客户端收集一些信息,并将json序列化并发送到服务器,服务器稍后将其存储在数据库中。在服务器的tcp服务模块中,我有代码从列表中的字符串加载json对象,然后将它们附加到另一个列表中这样(查看bind_and_listen
内的循环,以for client in clients
开头):
""" TCP Server before the main database. """
import socket
import sys
import logging
import json
import structs.client_data as cl_data
import db.register as register
cursor = register.cursor
client_list = []
domain_list = []
# connection constants
HOST = None
PORT = None
def config_server(host, port):
""" Configure the server's address and port. """
if not host:
logging.warning("HOST not supplied in the configuration file.")
sys.exit(-1)
if not port:
logging.warning("PORT not supplied in the configuration file.")
sys.exit(-1)
global HOST
global PORT
HOST = host
PORT = int(port)
def handle_files_question(request):
""" Read the file policy from the database for the server that sent it.
Params:
@request: The request as sent from the server.
"""
index = request.find(':')
hostname = request[index + 1:]
return register.query_file_policy(hostname)
def handle_size_question(request):
""" Read the size policy from the database for the server that sent it.
Params:
@request: The request as sent from the server.
"""
index = request.find(':')
hostname = request[index + 1:]
return register.query_size_policy(hostname)
def bind_and_listen():
""" Bind the server to the socket, and listen for incoming connections. """
serv = None
# create the socket
try:
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, v:
message = "Failed to create a socket: Message is {} and error code is {}"
errno, errormsg = v # is a (errno, message) tuple
message = message.format(errormsg, errno)
logging.error(message)
print message
sys.exit(-1)
# bind out socket to the address
try:
serv.bind((HOST, PORT)) # the double parens are to create a tuple with one element
except socket.error, msg:
message = "Binding of the socket failed. Error Code : {} Message: {}."
message = message.format(msg[0], msg[1])
logging.error(message)
print message
sys.exit(-2)
serv.listen(5) # 5 is the maximum number of queued connections we will allow
logging.info("Server is now listening on port %d" % (PORT,))
# we have the try block here only to facilitate the finally block
# that follows, so that we can reliably close the database everytime
# we have to close the program, but we don't have an exception raised
# everytime a client disconnects, the db is closed, and the networking
# module attempts to use the cursor of the expired connection.
try:
while True:
conn, addr = serv.accept()
hostname = None
output = str()
# this is the code handling the first policy question, regarding files
# 256 bytes should be enough to specify the question and hostname
res = conn.recv(256)
output = res
if output.startswith('files'):
files = handle_files_question(output)
conn.send(str(files))
# reset the output string
output = str()
# repeat the above procedure for the size policy question
res = conn.recv(256)
output = res
if output.startswith('size'):
size = handle_size_question(output)
conn.send(str(size))
# reset the output string
output = str()
# handle the rest of the data that the client sends
# (mainly, the clients and domains lists)
while True:
res = conn.recv(1024)
if not res:
break
output += res
# at this point, we assume that we have the full output string
# so we will split it to a list of strings representing the json
# representation of our clients
output = output.split('---')
domains_index = output.index('Domains_list')
clients = output[0:domains_index - 1] # -1 to compensate for a newline in the list
print clients
domains = output[domains_index + 1:-1]
hostname = output[0].split()[1]
clients = clients[2:-1] # ignoring the hostname and the Clients_list delimiter
for client in clients:
jason = json.loads(client)
client = cl_data.Client(jason['client_id'], jason['login'], jason['pname'], jason['email'])
client.files = jason['files']
client.size = jason['size']
client.size_human = jason['size_human']
client.domains = jason['domains']
client.domain_num = jason['domain_num']
client_list.append(client)
# the code below seems to prevent the problem?
#for client in client_list:
# print client.pname
for domain in domains:
jason = json.loads(domain)
domain = cl_data.DomainName(jason['domain_id'], jason['name'], jason['client_id'])
domain_list.append(domain)
conn.close()
register.update_clients(hostname, client_list)
register.update_domains(hostname, domain_list)
logging.info("Connection from %s is terminated." % (addr,))
except KeyboardInterrupt:
message = "\nCtrl + C was pressed, and an interruption signal has been registered."
message += " Terminating the server now."
logging.info(message)
print message
finally:
register.close_connection()
此时一切都很好。完成循环后,我使用client_list
使用以下代码更新SQL数据库:
register.update_clients(hostname, client_list)
问题是,如果我在上面的代码之前添加print len(client_list)
之类的东西,我会得到1
,除非我做了类似的事情:
for client in client_list:
print client.email
在这种情况下,我得到列表中包含应该包含的所有对象(约180左右)。
从上面开始,我收集的是,由于某些我无法理解的原因,列表追加被优化了,除非我强制列表在第一个循环结束后立即迭代。有没有人对此有任何见解?这是标准的行为吗?我做错了什么?这是一个错误还是什么?
根据口译员和python 2.7.9
,debian 8 (jessie)
为/etc/os-release
。
(我知道我可以使用dis
模块进一步调查它,但是当我尝试将它导入python解释器时,模块的编写方式向我提供了一些ImportError
< / p>