I am weak in programming. I need to filter the data array according to the following logic, and I without understanding how to do it. Сan use the "while" loop, but I think it will take a lot of time since the array is very large.
I have very large array drivers for printers:
[...
{"PPD_NAME": "HP PSC 2500 Series, hpcups 3.18.5 (en)", "PPD_PATH": "hplip:4/ppd/hplip/HP/hp-psc_2500_series.ppd"},
{"PPD_NAME": "HP LaserJet m3035 MFP hpijs pcl3, 3.18.5 (en)", "PPD_PATH": "drv:///hpijs.drv/hp-laserjet_m3035_mfp-pcl3-hpijs.ppd"},
{"PPD_NAME": "HP LaserJet m2727 MFP pcl3, hpcups 3.18.5 (en)", "PPD_PATH": "drv:///hpcups.drv/hp-laserjet_m2727_mfp-pcl3.ppd"}
...]
And have string(name printer):
"HP HP LaserJet m2727 Multifunction Printer"
I want to split the string by words and filter the array by each word until there is "None".
Example:
Loop 1:
Word: "HP"
Result:
{"PPD_NAME": "HP PSC 2500 Series, hpcups 3.18.5 (en)", "PPD_PATH": "hplip:4/ppd/hplip/HP/hp-psc_2500_series.ppd"},
{"PPD_NAME": "HP LaserJet m3035 MFP hpijs pcl3, 3.18.5 (en)", "PPD_PATH": "drv:///hpijs.drv/hp-laserjet_m3035_mfp-pcl3-hpijs.ppd"},
{"PPD_NAME": "HP LaserJet m2727 MFP pcl3, hpcups 3.18.5 (en)", "PPD_PATH": "drv:///hpcups.drv/hp-laserjet_m2727_mfp-pcl3.ppd"}
Loop 2:
Word: "LaserJet"
Result:
{"PPD_NAME": "HP LaserJet m3035 MFP hpijs pcl3, 3.18.5 (en)", "PPD_PATH": "drv:///hpijs.drv/hp-laserjet_m3035_mfp-pcl3-hpijs.ppd"},
{"PPD_NAME": "HP LaserJet m2727 MFP pcl3, hpcups 3.18.5 (en)", "PPD_PATH": "drv:///hpcups.drv/hp-laserjet_m2727_mfp-pcl3.ppd"}
Loop 3:
Word: "m2727"
Result:
{"PPD_NAME": "HP LaserJet m2727 MFP pcl3, hpcups 3.18.5 (en)", "PPD_PATH": "drv:///hpcups.drv/hp-laserjet_m2727_mfp-pcl3.ppd"}
Loop 4:
Word: "Multifunction"
Result:
None
And I want to get the first object with the last iteration not "None": {"PPD_NAME": "HP LaserJet m2727 MFP pcl3, hpcups 3.18.5 (en)",{...}}
Provided that the result is "None" or the words are completed. How can I make a similar filter on python? Someone these?:
for word in ArgInListFindNewPrinters['PRINTER_INFO'].split():
name = next(name for name in ListPrinterDriver if re.search(word, str(name), re.IGNORECASE))
print name
but it doesn’t work as I expect.
EDIT: my result is lower. This script searches for a printer in CUPS (Available Printers) and adds it. If it can be optimized somehow, I will be grateful for the advice.
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
import json
import sys
from bs4 import BeautifulSoup
import re
def GetFindNewPrinters(cookie):
headers = {}
headers["Cookie"] = 'org.cups.sid='+cookie["org.cups.sid"]
FromData = {}
FromData["OP"] = 'find-new-printers'
FromData["org.cups.sid"] = cookie["org.cups.sid"]
Responce = requests.post(url, headers=headers, data=FromData)
soup = BeautifulSoup(Responce.content.decode('utf-8'), 'html.parser')
ListFindNewPrinters = []
for id, link in enumerate(soup.find_all('form')):
ListFindNewPrinters.append({'TEMPLATE_NAME': link.find("input", {"name":"TEMPLATE_NAME"})['value']})
ListFindNewPrinters[id]['DEVICE_URI'] = link.find("input", {"name":"DEVICE_URI"})['value']
ListFindNewPrinters[id]['PRINTER_LOCATION'] = link.find("input", {"name":"PRINTER_LOCATION"})['value']
ListFindNewPrinters[id]['PRINTER_INFO'] = link.find("input", {"name":"PRINTER_INFO"})['value']
return ListFindNewPrinters
def GetPrinterDrivers(cookie,PRINTER_NAME,PRINTER_INFO,PRINTER_LOCATION,DEVICE_URI):
headers = {}
headers["Cookie"] = 'org.cups.sid='+cookie["org.cups.sid"]
FromData = {}
FromData["OP"] = 'add-printer'
FromData["org.cups.sid"] = cookie["org.cups.sid"]
FromData["PRINTER_IS_SHARED"] = 'on'
FromData["PRINTER_LOCATION"] = PRINTER_LOCATION
FromData["PRINTER_INFO"] = PRINTER_INFO
FromData["PRINTER_NAME"] = PRINTER_NAME
FromData["DEVICE_URI"] = DEVICE_URI
FromData["PPD_MAKE"] = PRINTER_INFO.split(' ', 1)[0]
FromData["PPD_FILE"] = '(binary)'
Responce = requests.post(url, headers=headers, data=FromData)
soup = BeautifulSoup(Responce.content.decode('utf-8'), 'html.parser')
ListPrinterDriver = []
for id, link in enumerate(soup.find_all('option')):
ListPrinterDriver.append({'PPD_PATH': link['value']})
ListPrinterDriver[id]['PPD_NAME'] = link.next.replace("\n","")
return ListPrinterDriver
def FindInArrayByWord(ArrayDrivers,PrinterName):
if ArrayDrivers == []:
return None
for word in PrinterName.split():
if FindInArray(ArrayDrivers,word) == []:
break
else:
ArrayDrivers = FindInArray(ArrayDrivers,word)
return ArrayDrivers[0]
def AddPrinter(cookie,PRINTER_NAME,PRINTER_INFO,PRINTER_LOCATION,DEVICE_URI,PPD_NAME):
headers = {}
headers["Cookie"] = 'org.cups.sid='+cookie["org.cups.sid"]
FromData = {}
FromData["org.cups.sid"] = cookie["org.cups.sid"]
FromData["OP"] = 'add-printer'
FromData["printer_name"] = PRINTER_NAME
FromData["PRINTER_NAME"] = PRINTER_NAME
FromData["PRINTER_INFO"] = PRINTER_INFO
FromData["PRINTER_LOCATION"] = PRINTER_LOCATION
FromData["DEVICE_URI"] = DEVICE_URI
FromData["PRINTER_IS_SHARED"] = 'on'
FromData["PPD_NAME"] = PPD_NAME
FromData["MAX_FILE_SIZE"] = '262144'
FromData["PPD_FILE"] = '(binary)'
Responce = requests.post(url, headers=headers, data=FromData)
return Responce
def AddPrinterOptions(cookie,PRINTER_NAME):
headers = {}
headers["Cookie"] = 'org.cups.sid='+cookie["org.cups.sid"]
FromData = {}
FromData["org.cups.sid"] = cookie["org.cups.sid"]
FromData["PRINTER_NAME"] = PRINTER_NAME
FromData["OP"] = 'set-printer-options'
FromData["PageSize"] = 'A4'
FromData["PageSize.Width"] = '0'
FromData["PageSize.Height"] = '0'
FromData["PageSize.Units"] = 'pt'
FromData["Duplex"] = 'None'
FromData["job_sheets_start"] = 'none'
FromData["job_sheets_end"] = 'none'
FromData["printer_error_policy"] = 'retry-job'
FromData["printer_op_policy"] = 'default'
Responce = requests.post(url, headers=headers, data=FromData)
return Responce
def FindInArray(Array,Arg,*args):
ArrayObject = None
NewArray = []
if len(args) != 0:
for ArrayObjectName in args:
try:
ArrayObject = [name for name in Array if re.search(Arg, name[ArrayObjectName], re.IGNORECASE)]
except StopIteration: pass
else:
try:
ArrayObject = [name for name in Array if re.search(Arg, str(name), re.IGNORECASE)]
except StopIteration: pass
return ArrayObject
def main():
# Check connection
try:
Responce = requests.get(url, timeout=10)
except requests.exceptions.RequestException as e:
print e
sys.exit(-1)
# Get list available printers in CUPS, and find. Else add printer with specific destination.
if sys.argv[3] != 'False':
ArgPrinterIP = sys.argv[3]
ArgInListFindNewPrinters = {}
ArgInListFindNewPrinters["TEMPLATE_NAME"] = ArgPrinter.replace(" ", "_")
ArgInListFindNewPrinters["PRINTER_INFO"] = ArgPrinter
ArgInListFindNewPrinters["PRINTER_LOCATION"] = 'Добавленный по IP'
ArgInListFindNewPrinters["DEVICE_URI"] = 'socket://'+ArgPrinterIP
else:
ListFindNewPrinters = GetFindNewPrinters(Responce.cookies)
ArgInListFindNewPrinters = FindInArrayByWord(ListFindNewPrinters,ArgPrinter)
if ArgInListFindNewPrinters == None:
print "Not find printers with arguments."
sys.exit(1)
ListPrinterDriver = GetPrinterDrivers(Responce.cookies,ArgInListFindNewPrinters['TEMPLATE_NAME'],ArgInListFindNewPrinters['PRINTER_INFO'],ArgInListFindNewPrinters['PRINTER_LOCATION'],ArgInListFindNewPrinters['DEVICE_URI'])
Driver = FindInArrayByWord(ListPrinterDriver,ArgInListFindNewPrinters['PRINTER_INFO'])
AddPrinter(Responce.cookies,ArgInListFindNewPrinters['TEMPLATE_NAME'],ArgInListFindNewPrinters['PRINTER_INFO'],ArgInListFindNewPrinters['PRINTER_LOCATION'],ArgInListFindNewPrinters['DEVICE_URI'],Driver['PPD_PATH'])
AddPrinterOptions(Responce.cookies,ArgInListFindNewPrinters['TEMPLATE_NAME'])
print "Printer: "+ArgInListFindNewPrinters['TEMPLATE_NAME']+". Succesfull add."
# Set arguments
ArgURL = sys.argv[1]
ArgPrinter = sys.argv[2]
url = 'http://'+ArgURL+':631/admin/'
if __name__ == "__main__":
try:
main()
except Exception as e:
print e
sys.exit(0)
Uses a regular expression to match against desired filter.
import re
# List of printers
printers = [{"PPD_NAME": "HP PSC 2500 Series, hpcups 3.18.5 (en)", "PPD_PATH": "hplip:4/ppd/hplip/HP/hp-psc_2500_series.ppd"},
{"PPD_NAME": "HP LaserJet m3035 MFP hpijs pcl3, 3.18.5 (en)", "PPD_PATH": "drv:///hpijs.drv/hp-laserjet_m3035_mfp-pcl3-hpijs.ppd"},
{"PPD_NAME": "HP LaserJet m2727 MFP pcl3, hpcups 3.18.5 (en)", "PPD_PATH": "drv:///hpcups.drv/hp-laserjet_m2727_mfp-pcl3.ppd"}]
# List of filter words
filterby = "HP HP LaserJet m2727 Multifunction Printer"
# Separate into separate words
filterby_split = filterby.split()
# start with all filters
prev = printers[:]
for filt in filterby_split:
# regex to match current filter word
p = re.compile(r'\b' + filt + r'\b', flags = re.IGNORECASE)
# Generate list of printers which has the filter word
# filtering from previous list
current = [printer for printer in prev if p.search(printer["PPD_NAME"])]
if current: # there were some printers
prev[:] = current # copy to previous since found items in filter
else: # No printers found
current = prev # found none in last iteration
break
print(current[0]) # first object of last successful iteration