Abstract
First of all, the following categories of readers are invited to mark their seats:
- Those who are familiar with CMDB but new to Python are strongly advised to read the first few articles;
- This article is highly recommended for those who have little knowledge of Python and can only write simple scripts;
- This article is recommended for those who are comfortable writing Python scripts but not familiar with CMDB.
- For those of you who know both Python and CMDB, go out and turn left for the next one.
In the previous section to start programming the readers a little challenge, which involved through the loop to complex data structure changes, but as long as you seriously to understand the contents of the previous section, the content of this section will feel easier, in this section, we went on to read the rest of the CMDB for delete the section of code.
[I] Code optimization
Before we talk about pruning, we need to review the previous two sections of code to see if there are any improvements we can make.
import json
def init(region) :
with open("data.json"."r+") as f:
data = json.load(f)
if region in data:
print("region %s already exists" % region)
return
data[region] = {"idc": region, "switch": {}, "router": {}}
with open("data.json"."w+") as f:
json.dump(data, f, indent=2)
print(json.dumps(data, indent=2))
def add(path, attrs=None) :
if attrs is None:
print("add operation must have attrs arg")
return
try:
attrs = json.loads(attrs)
except Exception:
print("input attribute is an invalid json string")
return
with open("data.json"."r+") as f:
data = json.load(f)
path_seg = path.split("/") [1:]
target_path = data
for idx, seg in enumerate(path_seg):
if idx == len(path_seg)-1:
if seg in target_path:
print("%s already exists in %s, please use update operation" %
(seg, path))
return
target_path[seg] = attrs
break
target_path = target_path[seg]
with open("data.json"."w+") as f:
data = json.dump(data, f, indent=2)
print(json.dumps(data, indent=2))
Copy the code
Carefully before readers may have found that our new asset information function initializes the regional features and have access to the data source, and it looks as if the code is exactly the same, then have involved in the code refactoring principle, if a piece of code where two or more repeated writing, you will need to be reconstructed into individual method. This means that the access to the data source has been used in two places, and it is foreseeable that it will be used in the later deletion, so we need to abstract it into a separate function, so that it can be repeatedly called in different places, the code after reconstruction is as follows:
import json
def read_file() :
with open("data.json"."r+") as f:
data = json.load(f)
return data
def write_file(data) :
with open("data.json"."w+") as f:
json.dump(data, f, indent=2)
def init(region) :
data = read_file()
if region in data:
print("region %s already exists" % region)
return
data[region] = {"idc": region, "switch": {}, "router": {}}
write_file(data)
print(json.dumps(data, indent=2))
def add(path, attrs=None) :
if attrs is None:
print("add operation must have attrs arg")
return
try:
attrs = json.loads(attrs)
except Exception:
print("input attribute is an invalid json string")
return
data = read_file()
path_seg = path.split("/") [1:]
target_path = data
for idx, seg in enumerate(path_seg):
if idx == len(path_seg)-1:
if seg in target_path:
print("%s already exists in %s, please use update operation" %
(seg, path))
return
target_path[seg] = attrs
break
target_path = target_path[seg]
write_file(data)
print(json.dumps(data, indent=2))
Copy the code
As you can see, the amount of code that has been done is reduced with proper refactoring because we avoid redundant blocks of code, so programming is never about who writes more lines than who does better.
【 II 】 Update asset information
We also need five steps to think and practice the same function of updating asset information
- Consider what you need to do to implement this feature:
- Update what kind of information?
- How do I locate the path to update?
- Here I first in turn to you answer:
- How do you locate the path that you want to update and that’s what we talked about in the last video, for those of you who aren’t quite sure what to do
- The type of information we are updating is one area of concern, because our information can be in dictionary format, string or array format
- What we need to do now is to further refine our thinking into implementable pseudocode:
-
We need to define an update() function to do this, and this function needs to take two parameters, one is the information to update and the specified path to update the information, so our function signature should be update(path, attrs).
-
The attrs we pass in must be a JSON-formatted string, and the path we pass in must be a/delimited string
-
Path is used to locate the specified location in the data source hierarchically, and attrs is updated to the specified location in the data source via dictionary assignment
-
Data persistence via json.load and json.dump
- The next step is to write a pseudo-code that can achieve the above functions, as follows:
def update(path, attrs) :
# Judge the validity of attrs
if attrs is valid
Parse attrs to a Python type
attrs = parse_attrs()
Read the data source from a text file
data = read_file()
# Split the path
seg = path.split()
Locate the specified location of the data source based on the path
target_path = position_data()
Update attrs to the specified path
data[target_path] = attrs
Save the data to a text file
write_file(data)
# print data source
print(data)
Copy the code
You can see that the logic of update and add is very similar, and in fact the same is true of update and add in other real add, delete, change, and review scenarios.
- The final code for updating asset information is as follows:
def update(path, attrs=None) :
if attrs is None: # Judge the validity of attrs
print("add operation must have attrs arg")
return
try:
attr_json = json.loads(attrs)
except Exception:
print("attributes is not valid json string")
return
data = read_file()
target_path = data
path_seg = path.split("/")
for idx, seg in enumerate(path_seg[1:]):
if idx == len(path_seg)-2:
if seg not in target_path:
print("update path is not exists in data, please use add function")
return
if type(attrs) ! =type(target_path[seg]):
print("update attributes and target_path attributes are different type.")
return
if isinstance(attr_json, dict):
target_path[seg].update(attr_json)
elif isinstance(attr_json, list):
target_path[seg].extend(attr_json)
else:
target_path[seg] = attr_json
else:
target_path = target_path[seg]
write_file(data)
print(json.dumps(data, indent=2))
Copy the code
There are two key points to note about the update:
5.1 During the update operation, we are updating the existing path in the data source, which involves data security. If attrs is None, the original information may be cleared.
judgeattrs
The legitimacy of the
if attrs is None: # Judge the validity of attrs
print("add operation must have attrs arg")
return
Copy the code
None is an empty variable type in Python, so if we don’t get attrs from the command line, our program should give us a hint. Here I printed a reminder that adding assets must have the attrs argument. Then return directly to exit the function
5.2 The second point is that as for the type of updated information, we do not need to consider the type of attrs in the addition function because the information is added on the path that does not exist before, so we can directly use the characteristics of the dictionary to assign values. However, when updating, we need to make a more detailed judgment about the type of data because there is already data on the path.
Update the attributes
if seg not in target_path:
print("update path is not exists in data, please use add function")
return
if type(attrs) ! =type(target_path[seg]):
print("update attributes and target_path attributes are different type.")
return
if isinstance(attr_json, dict):
target_path[seg].update(attr_json)
elif isinstance(attr_json, list):
target_path[seg].extend(attr_json)
else:
target_path[seg] = attr_json
Copy the code
- You need to determine whether the path to update exists in the data source, and if it does not, you need to add it using the added functionality
- You need to specify the type and the path in the data source
attrs
If the type is different, it cannot be updated - If the path type specified in the data source is a dictionary, it can not be directly assigned. This will erase the original attribute information. This requires a dictionary feature
dict.update()
This function takes a parameter, merges two dictionaries, and updates the information in the original dictionary with the information in the parameter dictionary. - If the information type on the source path is array, then we need the information to be updated
attrs
To add to the original information, this uses a feature of arrayslist.extend()
This function takes a parameter and can merge the array of parameters after the original array.
**Tips: extend and Append **
Array: array: array: array: array: array: array: array: array: array
> my_list = [1.2.3] > new_list = [4.5] > my_list.append(new_list) > my_list # output [1, 2, 3, [4, 5]] > my_list.extend(new_list) > my_list # output [1, 2, 3, 4, 5] Copy the code
You can see that Append adds an element to the end of the original array, while extend consolidates the new array to the end, and you can see the difference by looking at the two method arguments
def append(self, __object: _T) - >None:.The # append method can accept arguments of any type as it simply appoints them to the end of the original array Copy the code
def extend(self, __iterable: Iterable[_T]) - >None:.The # extend method requires that the argument passed be of an iterable type, because it iterates over all elements of the argument, consolidating them into the end of the original array Copy the code
- If the information type on the source path is not a dictionary or array, it can be assigned directly
So far to update the function of the attributes have been finished, update, and add the logic of general type, but update USES logic, to a large number of readers about the statement there is a need and explain in detail, such as multiple logical judgement of the update methods, for example, many new to programming of readers may write like this:
if seg in target_path:
if type(attrs) == type(target_path[seg]):
if isinstance(attr_json, dict):
target_path[seg].update(attr_json)
elif isinstance(attr_json, list):
target_path[seg].extend(attr_json)
else:
target_path[seg] = attr_json
else:
print("update attributes and target_path attributes are different type.")
else:
print("update path is not exists in data, please use add function")
Copy the code
Through this multi-layered if… else… Nested, although also can achieve the same function, but for the readability of the code can be a big disaster, and late for multilayer nested logic changes is very difficult, so in programming at the same time we must try our best to avoid this kind of multilayer nested, standard is usually used for loop statement and the statement don’t exist more than three layer and nested. So when we encounter the above situation, we can refer to the code example I gave, first to determine the illegal logic, if the illegal logic is hit, directly throw an exception or exit the function, such a simple change will greatly improve the readability and maintainability of the code.
In this section, we mainly review the five steps at a time, and for the update function logic detailed interpretation, originally want to delete, and query is together in this section, but also fears that too many knowledge points, everyone is not so easy to accept, then I won’t take you step by step to practice five footwork, but it is a process of practice makes perfect, Hopefully you’ll be able to use it in your own practice, and we’ll see you in the next section.
After the article language
I do not know whether we have found in the learning of these several chapters, whether in programming or reading the source code before the logic comb is very important, and many parts of the code are the processing of some boundary cases, so for pseudo code abstraction can also help us better to understand the complex business logic. However, these boundary cases play a key role in the robustness of the code, so readers should also develop sensitivity to boundary cases when programming, to predict the possible logic of the code or business logic from different dimensions, and avoid it in advance.
In addition, although a lot of reader friend is new to programming, but we are still read from the form and source of programming thinking, to popularize something deeper, such as reconstruction principle, elegant and multi-layer nested processing, etc., so I was meant to put these knowledge when first learning to hear let everyone to know, It is not to say that beginners should memorize some basic methods and norms, which will be counterproductive for learning, so I hope you can read the article while carefully to feel the experience.
Welcome to add my personal public account [Python Playing automated Operation and Maintenance] to the reader exchange group, to get more dry content