Netmiko OSError: Search pattern never detected in send_command_expect: Destination - python

I'm stuck here for more than an hour but seem like not able to find the solution for my issue. Issue is that I'm not able to completely match the string output.
Actual output:
hostname#$192.168.1.1/out/c2960x-universalk9-mz.152-7.E3.bin flash:c2960x-universalk9-mz.152-7.E3.bin
Destination filename [c2960x-universalk9-mz.152-7.E3.bin]?
my code not working:
commandsend = "copy ftp://206.112.194.143/out/c2960x-universalk9-mz.152-7.E3.bin flash:c2960x-universalk9-mz.152-7.E3.bin"
output = connection.send_command(commandsend,expect_string=r'Destination filename')
output += connection.send_command('\n',expect_string=r'#')
copy ftp://x.x.x.x/out/c2960x-universalk9-mz.152-7.E3.bin flash:c2960x-universalk9-mz.152-7.E3.bin
21:11:27.067 GMT Wed May 12 2021
Traceback (most recent call last):
File "./svu.py", line 292, in
output = uploading_update(models,ver[0],ver[1],ver[2],ver[3]) # Send to func {'CSR1000V': ['12.2.55',
File "./svu.py", line 119, in uploading_update
output = connection.send_command(commandsend,expect_string=r'Destination filename')
File "/home/repos/public/Python/lib/python3.6/site-packages/netmiko/base_connection.py", line 1112, in send_command
search_pattern))
OSError: Search pattern never detected in send_command_expect: Destination filename
I tried using the following but it still not working
output = connection.send_command(commandsend,expect_string=r'Destination.*')
output = connection.send_command(commandsend,expect_string='Destination.*')
output = connection.send_command(commandsend,expect_string=r'Destination filename.+')
I even tried adjusting the delay factor and fast_cli=False but still the same.
When I tried using the exact output. I'm seeing the below error.
output = connection.send_command(commandsend,expect_string=r'Destination filename [c2960x-universalk9-mz.152-7.E3.bin]? ')
bad character range x-u at position 27
I this a Bug or something? Any missing option I need to use?

The problem with your expect_string=r'Destination filename [c2960x-universalk9-mz.152-7.E3.bin]? ' is, that Netmiko interprets the expect_string parameter as a Regular Expression (regex) string, therefore what's inside the [ and ] brackets are treated as a range of characters you're trying to match, that's where the error comes from.
In your case, you want to match the exact [ and ] characters, so you need to escape them using \ in 'raw' strings or \\ in 'normal' strings. The same applies to ? and . characters, which have special meaning in regex.
Therefore the right command would be:
output = connection.send_command(commandsend,expect_string=r'Destination filename \[c2960x-universalk9-mz\.152-7\.E3\.bin\]\? ')
You can use online regex tools such as regex101 to help you build and test your regexes.
Also, if you are dealing with Cisco, I think you should look at file prompt quiet command, which disables these kinds of prompts.

Related

Open an external file in python

x = open('Homework','r')
print(x.name)
x.close()
I got this error when I run the code.
File "C:/Users/LENOVO/Desktop/pythonhome/tobechanged.py", line 16, in <module>
x = open('Homework','r')
FileNotFoundError: [Errno 2] No such file or directory: 'Homework'
SO I tried to type the full path
x = open('C:\Users\LENOVO\Desktop\pythonhome','r')
print(x.name)
x.close()
I got an Unicode error.
btw I'm using windows.
As the comments mentioned, it's usually good to type out the full path to the file, because running a script in IDLE, for example, can cause Python to search for the file in a directory that you are not intending. The reason you got the Unicode error is because you are using a special character, the backslash (\) which starts something known as an escape sequence. Escape sequences allow coders to specify special characters, like the newline character: \n. You can read more about these in Python's docs here
You have to either use a raw string (a string preceded with r, like this r'C:\Users\...'), or escape these characters with double backslashes, like this: C:\\Users\\....
Additionally, you need to specify the extension for the Homework file, otherwise the file system won't be able to find the file you are referring to, resulting in the FileNotFoundError you encountered. As #tdelaney mentioned, these extensions may be hidden by default in Windows Explorer.
Also, the recommended way in Python to open files is using the with statement, as this handles closing the object for you. Here is a sample (assuming that the extension of the Homework file is .txt):
with open('C:\\Users\\LENOVO\\Desktop\\pythonhome\\Homework.txt', 'r') as x:
print(x.name)
It is because you are forgetting the extension to the file (the ending of it). For example, if you have a text file that is named Homework, you would include it in like this
open(r'Homework.txt','r')
For this example, it must be in the same directory as your script. If you wanted to open a file outside of your scripts directory, you would have to find the full path of it. Here is an example of the Homework.txt file in my downloads folder.
open(r'C:\Users\USER\Downloads\Homework.txt','r')
You can also see in this code I use an r infront of the path. This tells Python the expression is a raw string and escape sequences are not parsed.

Why python2 shows \r (Raw escaped) and python3 does not?

I have been having a path error: No file or directory found for hours. After hours of debugging, I realised that python2 added an invisible '\r' at the end of each line.
The input: (trainval.txt)
Images/K0KKI1.jpg Labels/K0KKI1.xml
Images/2KVW51.jpg Labels/2KVW51.xml
Images/MMCPZY.jpg Labels/MMCPZY.xml
Images/LCW6RB.jpg Labels/LCW6RB.xml
The code I used to debug the error
with open('trainval.txt', "r") as lf:
for line in lf.readlines():
print ((line),repr(line))
img_file, anno = line.strip("\n").split(" ")
print(repr(img_file), repr(anno))
Python2 output:
("'Images/K0KKI1.jpg'", "'Labels/K0KKI1.xml\\r'")
('Images/2KVW51.jpg Labels/2KVW51.xml\r\n', "'Images/2KVW51.jpg Labels/2KVW51.xml\\r\\n'")
("'Images/2KVW51.jpg'", "'Labels/2KVW51.xml\\r'")
('Images/MMCPZY.jpg Labels/MMCPZY.xml\r\n', "'Images/MMCPZY.jpg Labels/MMCPZY.xml\\r\\n'")
("'Images/MMCPZY.jpg'", "'Labels/MMCPZY.xml\\r'")
('Images/LCW6RB.jpg Labels/LCW6RB.xml\r\n', "'Images/LCW6RB.jpg Labels/LCW6RB.xml\\r\\n'")
("'Images/LCW6RB.jpg'", "'Labels/LCW6RB.xml\\r'")
Python3 output:
Images/K0KKI1.jpg Labels/K0KKI1.xml
'Images/K0KKI1.jpg Labels/K0KKI1.xml\n'
'Images/K0KKI1.jpg' 'Labels/K0KKI1.xml'
Images/2KVW51.jpg Labels/2KVW51.xml
'Images/2KVW51.jpg Labels/2KVW51.xml\n'
'Images/2KVW51.jpg' 'Labels/2KVW51.xml'
Images/MMCPZY.jpg Labels/MMCPZY.xml
'Images/MMCPZY.jpg Labels/MMCPZY.xml\n'
'Images/MMCPZY.jpg' 'Labels/MMCPZY.xml'
Images/LCW6RB.jpg Labels/LCW6RB.xml
'Images/LCW6RB.jpg Labels/LCW6RB.xml\n'
'Images/LCW6RB.jpg' 'Labels/LCW6RB.xml'
As annoying as it was, it was that small '\r' who caused the path error. I could not see it in my console until I write the script above. My question is: Why is this '\r' even there? I did not create it. Something somewhere added it there. It would be helpful if someone could tell me what is the use of this small 'r' , why did it appear in python2 and not in python3 and how to avoid getting bugs due to it.
there's probably a subtle difference of processing between Windows text file in python 2 & 3 versions.
The issue here is that your file has a Windows text format, and contains one or several carriage return chars before the linefeed. A quick & generic fix would be to change:
img_file, anno = line.strip("\n").split(" ")
by just:
img_file, anno = line.split()
Without arguments str.split is very smart:
it splits according to any kind of whitespace (linefeed, space, carriage return, tab)
it removes empty fields (no need for strip after all)
So use that cross-platform/python version agnostic form unless you need really specific split operation, and your problems will be history.
As an aside, don't do for line in lf.readlines(): but just for line in lf:, it will read & yield the lines one by one, handy when the file is big so you don't consume too much memory.

os.listdir works in console but fails in a script

My script uses os.listdir to get a list of directories to use later for batch analysis.
when running
mypath='//home//user//Documents//data'
datalist=os.listdir(mypath)
in console, I get the correct answer.
However, when I use the same code as a part of the script, python falls over on the datalist line
FileNotFoundError: [Errno 2] No such file or directory: '//home//user//Documents//data//'
Quoted from here:
The r'..' string modifier causes the '..' string to be interpreted
literally. That means, r'My\Path\Without\Escaping' will evaluate to
'My\Path\Without\Escaping' - without causing the backslash to escape
characters. The prior is equivalent to 'My\\Path\\Without\\Escaping'
string, but without the raw modifier.
And there is an explanation with a simple example at this link.
So use
mypath = r'\home\user\Documents\data'

Opening a file and matching Engr Label

1.Getting buildid from a buildlocation which is the last word after "\" which is "A1234ABCDE120083.1" in this case
2.After getting the buildid,am opening a file and then trying to match the line "Engr Label: Data_CRM_PL_177999" to get the label name which is "Data_CRM_PL_177999"
3.Final output should be "Data_CRM_PL_177999"
For some reason I am getting the following syntax error..
import re
Buildlocation= '\\umor\locations455\INT\A1234ABCDE120083.1'
Labelgetbuildlabel(Buildlocation)
def getbuildlabel(BuildLocation):
buildid=BuildLocation.split('\')[-1]
Notes=os.path.join(BuildLocation,Buildid + '_notes.txt')
if os.path.exists(Notes):
try:
open(Notes)
except IOError as er:
pass
else:
for i in Notes.splitlines:
if i.find(Engr Label)
label=i.split(:)[-1]
print label//output should be Data_CRM_PL_177999
Output should be:-
Line looks like below in the file
Engr Label: Data_CRM_PL_177999
SYNTAX ERROR
buildid=BuildLocation.split('\')[-1]
^
SyntaxError: EOL while scanning string literal
In the line
buildid=BuildLocation.split('\')[-1]
The backslash is actually escaping the following quotation mark
So, Python thinks this is actually your string:
'[-1])
Instead, you should do the following:
buildid=BuildLocation.split('\\')[-1]
And Python will interpret your string to be
\\
Interestingly, StackOverflow's syntax highlighter hints at this issue. If you look at your code, it treats everything after that first slash as part of the string, all the way to the end of your code sample.
You also have a few other issues in your code, so I tried cleaning it up a bit for you. (However, I don't have a copy of the file, so obviously, I wasn't able to test this)
import re
import os.path
build_location= r'\\umor\locations455\INT\A1234ABCDE120083.1'
label = get_build_label(build_location)
# Python prefers function and variable names to be all lowercase with
# underscore separating words.
def get_build_label(build_location):
build_id = build_location.split('\\')[-1]
notes_path = os.path.join(build_location, build_id + '_notes.txt')
# notes_path is the filename (a string)
try:
with open(notes_path) as notes:
# The 'with' keyword will automatically open and close
# the file for you
for line in notes:
if line.find('Engr Label'):
label = line.split(':')[-1]
return label
except IOError:
# No need to do 'os.path.exists' since notes_path doesn't
# exist, then the IOError exception will be raised.
pass
print label
The backslash is escaping the ' character (see the escape codes documentation)
Try this line instead:
buildid=BuildLocation.split('\\')[-1]
Now you have a backslash escaping the backslash, so your string is a literal backslash. The other thing you could do would be to tell Python that this string doesn't have any escape codes by prefixing it with an r like this:
buildid=BuildLocation.split(r'\')[-1]
You've got a number of other problems as well.
The comment character in Python is #, not //.
I think you're also confusing a filename with a file object.
Notes is the name of the file you're trying to open. Then, when you call open(Notes), you will get back a file object that you can read data from.
So you should probably replace:
open(Notes)
with
f = open(Notes)
And then replace:
for i in Notes.splitlines:
with
for line in f:
When you do a for loop over a file object, Python will automatically give you a line at a time.
Now you can check each line like this:
if line.find("Engr Label") != -1:
label = line.split(':')[-1]

how to find a string in a text file and print the lines right before and after

I am trying to convert my shell scripts into python code, but I am stuck while trying this operation.
I have a process that outputs a text file, the file has sections like this:
Running Operation kdasdakdnaskdaksdma
(error if present) error: kdmakmdasmdaksom
This file could have multiple lines for the operation and the error (if present, otherwise the next line will just have another operation); there is always a crlf after each block.
I am trying to scan the file to find the line that contains "error:", and then read the operation that caused the error and the details of the error, so i can extrapolate it from the text file and save it in an error log file.
So far i can find the line(s) that has "error:" in it, with this simple code, but I am not able to find any example about how do you actually print the lines that are not necessarily the ones that contain the error message, but the ones that came before and after the line where "error:" is located.
using awk or grep would be straightforward, but with Python I am not really sure about how to do so; this is what i have so far, that is able to print the line that has the error but it prints just that, while i would like to have control to the lines printed before and after.
import re
fh = open('~/logs_output.txt')
for line in fh:
if "error:" in line:
print line
Tried to look at RE module in python, and also to the string modules, but so far I haven't found anything that would allow me to do what you would do with awk for example, where you can look for an occurrence of a specific string and turn on print, and then turn it off, once that you are done
Can anyone point me to the right direction to tackle this issue? Thanks!
import re
ss = '''qhvfgbhgozr
yytuuuyuyuuuyuyuuyy
jhfg tryy error jjfkhdjhfjh ttrtr
aaaeeedddeedaeaeeaeeea
jhzdgcoiua zfaozifh cohfgdyg fuo'''
regx = re.compile('^(.*)\r?\n(.*?error.*)\r?\n(.*)', re.MULTILINE)
print regx.search(ss).groups()
result
('yytuuuyuyuuuyuyuuyy', 'jhfg tryy error jjfkhdjhfjh ttrtr', 'aaaeeedddeedaeaeeaeeea')

Categories