Socket Connection: Python - python

So I'm trying to send several iterations of a barcode file to a device. This is the relevant part of the code:
# Start is the first barcode
start = 1234567
# Number is the quantity
number = 3
with open('barcode2.xml', 'rt') as f:
tree = ElementTree.parse(f)
# Iterate over all elements in a tree for the root element
for node in tree.getiterator():
# Looks for the node tag called 'variable', which is the name assigned
# to the accession number value
if node.tag == "variable":
# Iterates over a list whose range is specified by the command
# line argument 'number'
for barcode in range(number):
# The 'A-' prefix and the 'start' argument from the command
# line are assigned to variable 'accession'
accession = "A-" + str(start)
# Start counter is incremented by 1
start += 1
# The node ('variable') text is the accession number.
# The acccession variable is assigned to node text.
node.text = accession
# Writes out to an XML file
tree.write("barcode2.xml")
header = "<?xml version=\"1.0\" standalone=\"no\"?>\n<!DOCTYPE labels SYSTEM \"label.dtd\">\n"
with open("barcode2.xml", "r+") as f:
old = f.read()
f.seek(0)
f.write(header + old)
# Create socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to server
host = "xxx.xx.xx.x"
port = 9100
sock.connect((host, port))
# Open XML file and read its contents
target_file = open("barcode2.xml")
barc_file_text = target_file.read()
# Send to printer
sock.sendall(barc_file_text)
# Close connection
sock.close()
This is very much a version one.
The device is failing to receive the files after the first one. Could this be because the port is being reused again too quickly? What's a better way to architect this? Thanks so much for your help.

target_file = open("barcode2.xml")
barc_file_text = target_file.read()
sock.sendall(barc_file_text)
sock.close()
The socket gets closed, but the file doesn't. The next time through the loop, there is already a lock on the file when you get to the with open... part.
Solution: Use with open... here as well. Also, you don't need to baby-step everything; don't give something a name (by assigning it to a variable) if it isn't important.
with open("barcode2.xml", "r") as to_send:
sock.sendall(to_send.read())
sock.close()

Related

Python writing twice but randomly?

So I am currently working on a program that was handed down to me from a previous coworker and I am working through a strange bug. When reading data output from 2 separate serial sources byte by byte, python will write to the same cell in the .csv file as well as the console.
import serial
from datetime import datetime
import os
pressure_passed = False
arduino_passed = False
file_passed = False
BAUD_RATE = 115200
GARBAGE_CYCLES = 3 # how many cycles to ignore before logging data
garbage_cycle = 0
# Save data to log file
def LogData(startTime, pressureData, arduinoData, file):
global garbage_cycle
if garbage_cycle < GARBAGE_CYCLES:
garbage_cycle += 1
else:
delta = datetime.now() - startTime
ms = delta.total_seconds() * 1000
dataString = "{:0.2f}, {}, {}\n".format(ms, pressureData, arduinoData)
file.write(dataString)
file.flush()
print(dataString, end = "")
# Get the COM port for the Mark-10 Series 5
while not pressure_passed:
try:
pressure_com = input("Enter Mark-10 Series 5 COM Port #: ")
pressure_ser = serial.Serial("COM" + str(pressure_com), BAUD_RATE)
pressure_passed = True
except:
print("Invalid COM Port, please enter a valid port.\n-----")
# Get the COM port for the Arduino
while not arduino_passed:
try:
arduino_com = input("Enter Ardunio COM Port #: ")
arduino_ser = serial.Serial("COM" + str(arduino_com), BAUD_RATE)
arduino_passed = True
except:
print("Invalid COM Port, please enter a valid port.\n-----")
# Get the name for the log file
while not file_passed:
try:
file_name = input("Enter log file name: ")
# Add extension if not already given
if "." not in file_name:
file_name += ".csv"
log_file = open(file_name, "a")
# Add header row to log file
if os.stat(log_file.name).st_size == 0:
log_file.write("time (ms), pressure, rate (deg/ms)")
file_passed = True
except:
print("Invalid file, or could not open the file specified.\n-----")
start = datetime.now()
# Variables to read serial input
pressure_data = ""
last_pressure = ""
arduino_data = ""
last_arduino = ""
# Main program loop
# Serial is read from byte by byte to better sync the two devices
while True:
try:
x_changed = False
y_changed = False
# Read from Mark-10 serial if available
# x is a byte read from the serial line, converted to ascii
if pressure_ser.in_waiting > 0:
x = pressure_ser.read().decode('ascii')
x_changed = True
# Read from Arduino serial if available
# y is a byte read from the serial line, converted to ascii
if arduino_ser.in_waiting > 0:
y = arduino_ser.read().decode('ascii')
y_changed = True
# If new data received, check if we should log it
if x_changed:
if x == '\n': # New line detected, log the accumulated data
if last_pressure != pressure_data:
LogData(start, last_pressure, last_arduino, log_file)
last_pressure = pressure_data
pressure_data = ""
elif x != '\r': # Otherwise, add the read character to the string
pressure_data += x
if y_changed:
if y == '\n': # New line detected, log the accumulated data
if last_arduino != arduino_data:
LogData(start, last_pressure, last_arduino, log_file)
last_arduino = arduino_data
arduino_data = ""
elif y != '\r': # Otherwise, add the read character to the string
arduino_data += y
except Exception as e:
print(e)
if arduino_ser.isOpen():
arduino_ser.close()
if pressure_ser.isOpen():
pressure_ser.close()
log_file.close()
break
Here is what the file is spitting out, IE the double printing to a single cell. Sample of the data
Any advice is much appreciated, thank you all!
It looks like when a new pressure is read in, but the value has not changed from last time, then it's not resetting the string that's accumulating all the characters and it doubles up. Then on the next pass, when the REAL pressure hasn't changed, it compares the doubled to the non-doubled and writes again, and vice-versa.
Try unindenting the line that resets the string to remove it from the if clause:
# If new data received, check if we should log it
if x_changed:
if x == '\n': # New line detected, log the accumulated data
if last_pressure != pressure_data:
LogData(start, last_pressure, last_arduino, log_file)
last_pressure = pressure_data
pressure_data = ""
elif x != '\r': # Otherwise, add the read character to the string
pressure_data += x
Then the same thing for the arduino value block.
Your logs will probably be much shorter now.
I like your username! My guess is that it is reading from the serial too quickly and going through the loop twice before the arduino has time to change the value of in_waiting.
At the top of your code add:
import time
And in the LogData function add:
time.sleep(0.1)
Give that a shot and let me know if it helps. 0.1s may be too long for your application but it is a good test to see if this is the issue. If it is, you can play around with the amount of time it sleeps.
Based on the sample output provided, I think it's not writing twice but rather the following specific condition is met occasionally which calls two identical LogData() lines.
Only when Condition 1 AND Condition 2 are met - the data is written "twice". Note that the LogData() call is same in both conditions.
Condition 1:
# If new data received, check if we should log it
if x_changed:
if x == '\n': # New line detected, log the accumulated data
if last_pressure != pressure_data:
LogData(start, last_pressure, last_arduino, log_file)
Condition 2:
if y_changed:
if y == '\n': # New line detected, log the accumulated data
if last_arduino != arduino_data:
LogData(start, last_pressure, last_arduino, log_file)

How to convert a text file in a set line range to json format by Python

I consider to use a for loop to read a file, but I only want to read specific block .Then convert into json format.
Example:
# Summary Report #######################
System time | 2020-02-27 15:35:32 UTC (local TZ: UTC +0000)
# Instances ##################################################
Port Data Directory Nice OOM Socket
===== ========================== ==== === ======
0 0
# Configuration File #########################################
Config File | /etc/srv.cnf
[server]
server_id = 1
port = 3016
tmpdir = /tmp
[client]
port = 3016
# management library ##################################
# The End ####################################################
txt file
capture specific block:
[server]
server_id = 1
port = 3016
tmpdir = /tmp
[client]
port = 3016
block content
The resulting json is:
{
"server": {
"server_id":"1",
"port":"3016",
"tmpdir":"/tmp"
},
"client": {
"port": "3016"
}
}
resulting json
Is there any built-in feature to achieve this?
I tried to use the following to parse text file. But it did not work.
import json
filename = 'conf.txt'
commands = {}
with open(filename) as fh:
for line in fh:
command, description = line.strip().split('=', 1)
commands[command.rstrip()] = description.strip()
print(json.dumps(commands, indent=2, sort_keys=True))
First of all, never post screenshots, use the editor to type out the text.
You have to edit based on your requirements, it makes some assumptions based on your sample.
sample_input.txt
## SASADA
# RANDOM
XXXX
[server]
server_id = 1
port = 8000
[client]
port = 8001
code.py
all_lines = open('sample_input.txt', 'r').readlines() # reads all the lines from the text file
# skip lines, look for patterns here []
final_dict = {}
server = 0 # not yet found server
for line in all_lines:
if '[server]' in line:
final_dict['server'] = {}
server = 1
if '[client]' in line:
final_dict['client'] = {}
server = 2
if server == 1:
try:
clean_line = line.strip() # get rid of empty space
k = clean_line.split('=')[0] # get the key
v = clean_line.split('=')[1]
final_dict['server'][k] = v
except:
passs
if server == 2:
# add try except too
clean_line = line.strip() # get rid of empty space
k = clean_line.split('=')[0] # get the key
v = clean_line.split('=')[1]
final_dict['client'][k] = v
You can read all lines from a file_handle in the following way.
def read_lines(file_path, from_index, to_index):
with open(file_path, 'r') as file_handle:
return file_handle.readlines()[from_index:to_index]
Next part is processing the selected lines to json

Why there is double\r\n instead of \r\n in the codes

original codes from PY4E:
import socket
import time
HOST = 'data.pr4e.org'
PORT = 80
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect((HOST, PORT))
mysock.sendall(b'GET http://data.pr4e.org/cover.jpg HTTP/1.0\n\n')
count = 0
picture = b""
while True:
data = mysock.recv(5120)
if (len(data) < 1): break
time.sleep(0.25)
count = count + len(data)
print(len(data), count)
picture = picture + data
mysock.close()
# Look for the end of the header (2 CRLF)
pos = picture.find(b"\r\n\r\n")
print('Header length', pos)
print(picture[:pos].decode())
# Skip past the header and save the picture data
picture = picture[pos+4:]
fhand = open("stuff.jpg", "wb")
fhand.write(picture)
fhand.close()
my questions are little more:
what is the mean of picture=b''
what is pos for?
What is [pos+4:] inpicture=picture[pos+4:] for?
How can I view the image?
Thanks for any guidance in advance.
what is the mean of picture=b''
This is setting the picture variable to an empty byte array, which will be added to later.
what is pos for?
In pos = picture.find(b"\r\n\r\n"), the code is looking for the end of the HTTP header that comes before the picture data.
What is [pos+4:] in picture=picture[pos+4:] for?
The comment above it explains it, it "Skips past the header" to just get the picture data.
How can I view the image?
In these two lines,
fhand = open("stuff.jpg", "wb")
fhand.write(picture)
the picture is saved to a file titled stuff.jpg, you should be able to double click in a file manager to open it.

Index Error: list index out of range in python

I have project in internet security class. My partner started the project and wrote some python code and i have to continue from where he stopped. But i don't know python and i was planning to learn by running his code and checking how it works. however when i am executing his code i get an error which is "IndexError: list index out of range".
import os
# Deauthenticate devices
os.system("python2 ~/Downloads/de_auth.py -s 00:22:b0:07:58:d4 -d & sleep 30; kill $!")
# renew DHCP on linux "sudo dhclient -v -r & sudo dhclient -v"
# Capture DHCP Packet
os.system("tcpdump -lenx -s 1500 port bootps or port bootpc -v > dhcp.txt & sleep 20; kill $!")
# read packet txt file
DHCP_Packet = open("dhcp.txt", "r")
# Get info from txt file of saved packet
line1 = DHCP_Packet.readline()
line1 = line1.split()
sourceMAC = line1[1]
destMAC = line1[3]
TTL = line1[12]
length = line1[8]
#Parse packet
line = DHCP_Packet.readline()
while "0x0100" not in line:
line = DHCP_Packet.readline()
packet = line + DHCP_Packet.read()
packet = packet.replace("0x0100:", "")
packet = packet.replace("0x0110:", "")
packet = packet.replace("0x0120:", "")
packet = packet.replace("0x0130:", "")
packet = packet.replace("0x0140:", "")
packet = packet.replace("0x0150:", "")
packet = packet.replace("\n", "")
packet = packet.replace(" ", "")
packet = packet.replace(" ", "")
packet = packet.replace("000000000000000063825363", "")
# Locate option (55) = 0x0037
option = "0"
i=0
length = 0
while option != "37":
option = packet[i:i+2]
hex_length = packet[i+2:i+4]
length = int(packet[i+2:i+4], 16)
i = i+ length*2 + 4
i = i - int(hex_length, 16)*2
print "Option (55): " + packet[i:i+length*2 ] + "\nLength: " + str(length) + " Bytes"
print "Source MAC: " + sourceMAC
Thank you a lot
The index error probably means you have an empty or undefined section (index) in your lists. It's most likely in the loop condition at the bottom:
while option != "37":
option = packet[i:i+2]
hex_length = packet[i+2:i+4]
length = int(packet[i+2:i+4], 16)
i = i+ length*2 + 4
Alternatively, it could be earlier in reading your text file:
# Get info from txt file of saved packet
line1 = DHCP_Packet.readline()
line1 = line1.split()
sourceMAC = line1[1]
destMAC = line1[3]
TTL = line1[12]
length = line1[8]
Try actually opening the text file and make sure all the lines are referred to correctly.
If you're new to coding and not used to understanding error messages or using a debugger yet, one way to find the problem area is including print ('okay') between lines in the code, moving it down progressively until the line no longer prints.
I'm pretty new to python as well, but I find it easier to learn by writing your own code and googling what you want to achieve (especially when a partner leaves you code like that...). This website provides documentation on in-built commands (choose your version at the top): https://docs.python.org/3.4/contents.html,
and this website contains more in-depth tutorials for common functions: http://www.tutorialspoint.com/python/index.htm
I think the variable line1 that being split does not have as much as 13 numbers,so you will get error when executing statement TTL = line1[12].
Maybe you do not have the same environment as your partner worked with ,so the result you get(file dhcp.txt) by executing os.system("") maybe null(or with a bad format).
You should check the content of the file dhcp.txt or add statement print line1 after line1 = DHCP_Packet.readline() to check if it has a correct format.

Python parsing complex text

I'm struggling to develop an algorithm that can edit the below snip of an XML file. Can anyone help with ideas? Requirements are to parse the file as input, remove the "cipher" that uses "RC4", and output a new xml file, with just "RC4" cipher removed. The problem is there are multiple "Connector" sections within the XML file. I need to read all of them, but only edit the one that uses port 443 and with a specific IP address. So the script would need to parse each Connector section one at a time, but discard the ones that don't have correct IP address and port. Have tried:
1. Using ElementTree XML parser. Problem is it doesn't output the new XLM file well - it's a mess. I need it prettified with python 2.6.
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="443"
redirectPort="443"
executor="tomcatThreadPool"
disableUploadTimeout="true"
SSLEnabled="true"
scheme="https"
secure="true"
clientAuth="false"
sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"
keystoreType="JKS"
keystoreFile="tomcat.keystore"
keystorePass="XXXXX"
server="XXXX"
ciphers="TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DH_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
TLS_DH_DSS_WITH_AES_128_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_RC4_128_SHA"
address="192.168.10.6">
Here was my code:
from xml.etree import ElementTree
print "[+] Checking for removal of RC4 ciphers"
file = "template.xml"
with open(file, 'rt') as f:
tree = ElementTree.parse(f)
f.close()
for node in tree.getiterator('Connector'):
if node.tag == 'Connector':
address = node.attrib.get('address')
port = node.attrib.get('port')
if "EMSNodeMgmtIp" in address and port == "443":
ciphers = node.attrib.get('ciphers')
if "RC4" in ciphers:
# If true, RC4 is enabled somewhere in the cipher suite
print "[+] Found RC4 enabled ciphers"
# Find RC4 specific cipher suite string, for replacement
elements = ciphers.split()
search_str = ""
for element in elements:
if "RC4" in element:
search_str = element
print "[+] Search removal RC4 string: %s" % search_str
# Replace string by removing RC4 cipher
print "[+] Removing RC4 cipher"
replace_str = ciphers.replace(search_str,"")
rstrip_str = replace_str.rstrip()
if rstrip_str.endswith(','):
new_cipher_str = rstrip_str[:-1]
#print new_cipher_str
node.set('ciphers', new_cipher_str)
tree.write('new.xml')
I included comments to explain what is going on.
inb4downvote
from lxml import etree
import re
xml = '''<?xml version="1.0"?>
<data>
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="443"
redirectPort="443"
executor="tomcatThreadPool"
disableUploadTimeout="true"
SSLEnabled="true"
scheme="https"
secure="true"
clientAuth="false"
sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"
keystoreType="JKS"
keystoreFile="tomcat.keystore"
keystorePass="XXXXX"
server="XXXX"
ciphers="TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DH_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
TLS_DH_DSS_WITH_AES_128_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_3DES_EDE_CBC_SHA,
TLS_RSA_WITH_RC4_128_SHA"
address="192.168.10.6"></Connector></data>'''
tree = etree.fromstring(xml)
root = tree.getroottree().getroot()
for connector in root.findall('Connector'):
port = connector.get('port')
ip = connector.get('address')
#change this to port/ip you want to remove
if port != '443' or ip != '192.168.10.6':
#removes child connector
connector.getparent().remove(connector)
continue
#here we use list comprehension to remove any cipher with "RC4"
ciphers = ','.join([x for x in re.split(r',\s*', connector.get('ciphers')) if 'RC4' not in x])
#set the modified cipher back
connector.set('ciphers', ciphers)
print etree.tostring(root, pretty_print=True)
If the XML tools don't preserve the original structure and formatting, dump them. This is a straightforward text-processing problem, and you can write a Python program to handle it.
Spin through the lines of the file; simply echo to the output anything other than a "cipher" statement. When you hit one of those:
Stuff the string into a variable.
Split the string into a list.
Drop any list element containing "RC4".
Print the resulting "cipher" statement in your desired format.
Return to normal "read-and-echo" processing.
Does this algorithm get you going?
Answer below. Basically had to read each of the Connector sections (there were 4) into a temporary list, to check if port and address are correct. If they are, then make a change to the Cipher by removing cipher string but only if RC4 cipher is enabled. So the code had to read in all of the 4 Connectors, one at a time, into a temporary list.
f = open('template.xml', 'r')
lines = f.readlines()
f.close()
new_file = open('new.xml', 'w')
tmp_list = []
connector = False
for line in lines:
if '<Connector' in line:
connector = True
new_file.write(line)
elif '</Connector>' in line:
connector = False
port = False
address = False
for a in tmp_list:
if 'port="443"' in a:
port = True
elif 'address="%(EMSNodeMgmtIp)s"' in a:
address = True
if port and address:
new_list = []
count = 0
for b in tmp_list:
if "RC4" in b:
print "[+] Found RC4 cipher suite string at line index %d: %s" % (count,b)
print "[+] Removing RC4 cipher string from available cipher suites"
# check if RC4 cipher string ends with "
check = b[:-1]
if check.endswith('"'):
tmp_str = tmp_list[count-1]
tmp_str2 = tmp_str[:-2]
tmp_str2+='"\n'
new_list[count-1] = tmp_str2
replace_line = b.replace(b,"")
new_list.append(replace_line)
else:
replace_line = b.replace(b,"")
new_list.append(replace_line)
else:
new_list.append(b)
count+=1
for c in new_list:
new_file.write(c)
new_file.write(' </Connector>\n')
else:
# Not port and address
for d in tmp_list:
new_file.write(d)
new_file.write(' </Connector>\n')
tmp_list = []
elif connector:
tmp_list.append(line)
else:
new_file.write(line)
new_file.close()

Categories

Resources