从入门到精通:带你掌握Python Requests库的全部技能

news2025/1/16 20:10:05

        目录

引言

安装

启动用户管理项目

requests响应

Session请求

为什么Session类可以保持会话

封装requests


引言

Python Requests库是Python语言中最为流行的HTTP客户端库之一。它提供了简单易用的API,让发送HTTP/1.1请求变得异常容易,支持常见的HTTP操作(例如GET、POST、PUT、DELETE等),同时还能够自动处理Cookie、Headers等信息。

如果你想在Python开发中使用HTTP协议进行数据交换,Requests库绝对是不可或缺的选择。不论你是初学者还是有经验的开发人员,本文都将从浅入深地解析Python Requests库,并带领读者逐步掌握其全部技能。

让我们一起来探索这个强大而又方便的Python HTTP客户端库吧!

安装

requests库是一个开源的库,我们可以在GitHub中随时获取源代码。——github地址

同时requests也提供了不错的官方文档https://requests.readthedocs.io/zh_CN/latest/

通过官方的仓库我们可以了解到。目前最新的版本支持的是python版本是2.7 3.5 3.6 3.7 3.8

所以在安装之前一定要确认一下自己的python版本是否能够支持。

python安装库非常的简单,我们直接通过pip来安装requests库。

 pip install requests

安装好之后我们先来测试一下。

首先我们进入ipython的交互环境。打开一下百度的网页的。

In [1]: import requests

In [2]: r = requests.get('https://www.baidu.com')

In [3]: r.text
Out[3]: '<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>ç\x99¾åº¦ä¸\x80ä¸\x8bï¼\x8cä½\xa0å°±ç\x9f¥é\x81\x93</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div cl
ass=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=ç\x99¾åº¦ä¸\x80ä¸\x8b class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>æ\x96°é\x97»</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao1 23</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>å\x9c°å\x9b¾</a> <a href=http://v.baidu.com name=tj_trvide o class=mnav>è§\x86é¢\x91</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>è´´å\x90§</a> <noscript> <a hr
ef=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>ç\x99»å½\x95</a> </noscript> <script>document.write(\'<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ \'" name="tj_login" class="lb">ç\x99»å½\x95</a>\');\r\n                </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">æ\x9b´å¤\x9a产å\x93\x81</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <
p id=lh> <a href=http://home.baidu.com>å\x85³äº\x8eç\x99¾åº¦</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使ç\x94¨ç\x99¾åº¦å\x89\x8då¿\x85读</a>&nbsp; <a href =http://jianyi.baidu.com/ class=cp-feedback>æ\x84\x8fè§\x81å\x8f\x8dé¦\x88</a>&nbsp;京ICPè¯\x81030173å\x8f·&nbsp; <im
g src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\r\n'

可以看到我们的通过导入的requests库,仅仅三行代码,就通过get方法成功的返回了百度首页的数据。使用起来十分方便。

启动用户管理项目

在开始之前我们先把我们之前编写的用户管理API启动一下。

好了成功启动了我们开始把。

GET请求

用户管理接口一共有三种表现形式。我们分别使用requests来请求试试。还是进入ipython的交互环境。

  • /user/

    In [85]: r = requests.get('http://127.0.0.1:8000/user/')
    
    In [86]: r.text
    Out[86]: '{"code": 200, "message": "success", "data": [{"id": 3, "name": "\\u968f\\u98ce\\u6325\\u624b", "sex": 1, "idcard": "123", "email": "1084502012@qq.com", "address": "123", "company": "123", "created_time": "2020-11-11T14:33:12.869Z"}]}'
    

    可以看到我们的这个是什么成功返回了,但是格式好像不太正确,被单引号圈起来了,因为text返回的是一个文本字符串的格式。

    但是我们的接口返回的是一个json格式的。

    所以我们需要获取json数据。

    In [87]: r.json()
    Out[87]:
    {'code': 200,
     'message': 'success',
     'data': [{'id': 3,
       'name': '锦都不二',
       'sex': 1,
       'idcard': '123',
       'email': '1084502012@qq.com',
       'address': '123',
       'company': '123',
       'created_time': '2020-11-11T14:33:12.869Z'}]}
    

    可以看到这样就成功的返回了json格式的数据。

  • /user/1/

    In [10]: r = requests.get('http://127.0.0.1:8000/user/3/')
    
    In [11]: r.json()
    Out[11]:
    {'code': 200,
     'message': 'success',
     'data': {'id': 3,
      'name': '锦都不二',
      'sex': 1,
      'idcard': '123',
      'email': '1084502012@qq.com',
      'address': '123',
      'company': '123'}}
    
  • /user/?name=随风

    那么这个参数是怎么去访问呢。get方法是可以在后面通过?key=value&key2=value2的一个方式来进行请求的,那么我们先来看看这样的一个方式怎么样来进行的呢。

    In [12]: r = requests.get('http://127.0.0.1:8000/user/?name=随风')
    In [13]: r.json()
    Out[13]:
    {'code': 200,
     'message': 'success',
     'data': [{'id': 3,
       'name': '锦都不二',
       'sex': 1,
       'idcard': '123',
       'email': '1084502012@qq.com',
       'address': '123',
       'company': '123',
       'created_time': '2020-11-11T14:33:12.869Z'}]}
    

    可以看到直接把参数附加在请求地址的后面也可以进行访问。

    那有没有更加简便的方法呢。在requests库中提供了一个更加简单的方法。

    首先我们阅读一下requests库的源码。下图。可以看到有一个params参数,通过这个参数呢。

    def get(url, params=None, **kwargs):
        r"""Sends a GET request.
    
        :param url: URL for the new :class:`Request` object.
        :param params: (optional) Dictionary, list of tuples or bytes to send
            in the query string for the :class:`Request`.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :return: :class:`Response <Response>` object
      :rtype: requests.Response
        """
    
        kwargs.setdefault('allow_redirects', True)
        return request('get', url, params=params, **kwargs)
    

    那我们来试试这种方式把。

    In [17]: payload = {'name':'不二'}
    
    In [18]: r = requests.get('http://127.0.0.1:8000/user/',params=payload)
    
    In [19]: r.json()
    Out[19]:
    {'code': 200,
     'message': 'success',
     'data': [{'id': 3,
       'name': '锦都不二',
       'sex': 1,
       'idcard': '123',
       'email': '1084502012@qq.com',
       'address': '123',
       'company': '123',
       'created_time': '2020-11-11T14:33:12.869Z'}]}
    

    可以看到这种方式更简洁清晰明了。推荐使用这种方式。

    当然同时也支持一个键多个值的同时查找,需要在键值对中指定值为列表的方式。

    In [20]: payload = {'name':['不','二']}
    
    In [21]: r = requests.get('http://127.0.0.1:8000/user/',params=payload)
    
    In [22]: r.json()
    Out[22]:
    {'code': 200,
     'message': 'success',
     'data': [{'id': 3,
       'name': '锦都不二',
       'sex': 1,
       'idcard': '123',
       'email': '1084502012@qq.com',
       'address': '123',
       'company': '123',
       'created_time': '2020-11-11T14:33:12.869Z'}]}
    

POST请求

post请求一般都是提交一个表单,在requests的post请求中提供了两个参数。看下源码吧。

def post(url, data=None, json=None, **kwargs):
    r"""Sends a POST request.

    :param url: URL for the new :class:`Request` object.
    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
        object to send in the body of the :class:`Request`.
    :param json: (optional) json data to send in the body of the :class:`Request`.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    """

    return request('post', url, data=data, json=json, **kwargs)

分别是datajson,这两个都是传递参数的。其中data传的是表单参数,而json传递的是content_type=application/json的数据类型的。所以我们先来试试吧。先试一下json参数的post请求。

In [32]: data = {'name':'锦都不二11','sex':1,'idcard':'1234567','email':'1084502012@qq.com','address':'123','company'
    ...: :'123'}

In [33]: r = requests.post('http://127.0.0.1:8000/user/',json=data)

In [34]: r.json()
Out[34]:
{'code': 201,
 'message': 'created',
 'data': {'id': 4,
  'name': '锦都不二11',
  'sex': 1,
  'idcard': '1234567',
  'email': '1084502012@qq.com',
  'address': '123',
  'company': '123'}}

可以看到使用json参数成功的创建了一个新的用户。然后我们使用data参数来试试。

可以看到报错了,因为我编写的接口不支持非json格式数据的提交。这个报错太长了,所以我这里直接截图了。

那么我们怎么使用这个data参数呢。我手里面也没有合适的示例,直接用官方的演示吧。

In [40]: payload = {'key1': 'value1', 'key2': 'value2'}

In [41]: r = requests.post("http://httpbin.org/post", data=payload)

In [42]: r.text
Out[42]: '{\n  "args": {}, \n  "data": "", \n  "files": {}, \n  "form": {\n    "key1": "value1", \n    "key2": "value2"\n  }, \n  "headers": {\n    "Accept": "*/*", \n    "Accept-Encoding": "gzip, deflate", \n    "Content-Length": "23", \n    "Content-Type": "application/x-www-form-urlencoded", \n    "Host": "httpbin.org", \n    "User-Agent": "python-requests/2.24.0", \n    "X-Amzn-Trace-Id": "Root=1-5fabff48-70ea1f742434542615593b4b"\n  }, \n  "json": null, \n  "origin": "39.144.1.194", \n  "url": "http://httpbin.org/post"\n}\n'

这样通过data参数就成功提交了一个表单参数。

PUT请求

def put(url, data=None, **kwargs):
    r"""Sends a PUT request.

    :param url: URL for the new :class:`Request` object.
    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
        object to send in the body of the :class:`Request`.
    :param json: (optional) json data to send in the body of the :class:`Request`.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    """

    return request('put', url, data=data, **kwargs)

然后我们试一下put请求得一个方式。

In [51]: r = requests.put('http://127.0.0.1:8000/user/4/',json=data)

In [52]: r.json()
Out[52]:
{'code': 200,
 'message': 'updated',
 'data': {'id': 4,
  'name': '锦都不二11111',
  'sex': 1,
  'idcard': '1234567',
  'email': '1084502012@qq.com',
  'address': '123',
  'company': '123'}}

可以看到数据成功更新了。

DELETE方法

delete方法源码

def delete(url, **kwargs):
    r"""Sends a DELETE request.

    :param url: URL for the new :class:`Request` object.
    :param \*\*kwargs: Optional arguments that ``request`` takes.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response
    """

    return request('delete', url, **kwargs)

删除刚才创建的数据试试。

In [63]: r = requests.delete('http://127.0.0.1:8000/user/5/')

In [64]: r.status_code
Out[64]: 204

因为delete是删除方法,所以我们只需要查看一下它的状态码是204即可。至此我们的四种请求方式就说完了。

requests响应

在代码里面我们使用的r.textr.json()都是requests提供的响应方法。

我们结合官方文档在这里总结一下常用的响应结果吧。

方法描述
r.textRequests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。
r.json()返回json数据,如果数据不符合json格式规范,则会抛出异常
r.encoding查看返回的数据使用了什么编码
r.content使用字节的方式返回数据,通常用于图片等
r.status_code返回服务器响应的状态码,如200,400,500
r.raw返回响应的原始内容
r.headers返回服务器的响应头
r.url返回请求的地址数据
r.history返回请求的历史记录

这些都是requests库响应内容提供的一些方法。

Session请求

session意思就是会话,在很多的场景中都是存在依赖关系的,比如我之前些的接口测试框架中智学网的接口就是我需要先登录才可以访问其他的接口,那么我必须保持这登录结果传到下一个请求中,在这里举这个例子可能不是很恰当,因为这个示例的token是通过请求体传递的。
所以我们来看看官方的一个示例把。

import requests
s = requests.Session()
 
r1 = s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
print(r1.text)
#out: '{"cookies": {"sessioncookie": "123456789"}}'
 
r2 = s.get("http://httpbin.org/cookies")
print(r2.text)
#out '{"cookies": {"sessioncookie": "123456789"}}'

没有使用session会话保持的方式:

import requests
r1 = requests.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
print(r1.text)
#out: '{"cookies": {"sessioncookie": "123456789"}}'

r2 = requests.get("http://httpbin.org/cookies")
print(r2.text)
#out '{"cookies": {}}'

由于手头没有示例,所以只能继续先拿官方的示例来敷衍一下了。。。如果谁有好的网站可以分享一下。

为什么Session类可以保持会话

那么为什么session方法能够保持会话呢,而requests普通的getpost等方法不能保持会话呢。那我们就得来探究下requests的内部是怎么实现的。回顾上文的get方法源码,我们发现get方法内部调用的是request方法,看看这个方法里面实现了什么呢。

def request(method, url, **kwargs):
    """Constructs and sends a :class:`Request <Request>`.

    :param method: method for the new :class:`Request` object: ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
    :param url: URL for the new :class:`Request` object.
    :param params: (optional) Dictionary, list of tuples or bytes to send
        in the query string for the :class:`Request`.
    :param data: (optional) Dictionary, list of tuples, bytes, or file-like
        object to send in the body of the :class:`Request`.
    :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
    :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
    :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
    :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
        ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
        or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
        defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
        to add for the file.
    :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
    :param timeout: (optional) How many seconds to wait for the server to send data
        before giving up, as a float, or a :ref:`(connect timeout, read
        timeout) <timeouts>` tuple.
    :type timeout: float or tuple
    :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
    :type allow_redirects: bool
    :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
    :param verify: (optional) Either a boolean, in which case it controls whether we verify
            the server's TLS certificate, or a string, in which case it must be a path
            to a CA bundle to use. Defaults to ``True``.
    :param stream: (optional) if ``False``, the response content will be immediately downloaded.
    :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
    :return: :class:`Response <Response>` object
    :rtype: requests.Response

    Usage::

      >>> import requests
      >>> req = requests.request('GET', 'https://httpbin.org/get')
      >>> req
      <Response [200]>
    """

    # By using the 'with' statement we are sure the session is closed, thus we
    # avoid leaving sockets open which can trigger a ResourceWarning in some
    # cases, and look like a memory leak in others.
    with sessions.Session() as session:
        return session.request(method=method, url=url, **kwargs)

我们发现request方法的内部也是使用了Session类的对象来进行请求的,说明他也是可以支持会话保持的,但是他使用了with关键字,在python基础中with关键字的作用就是,处理事务后自动关闭,比如我们的读写文件。

with open('test.txt') as f:
    print(f.read())

我们都知道在使用with关键字后,文件with下面的内容被执行完毕后,文件会被自动关闭的,那么同样的在这个request方法也是一样的效果,在这次请求结束后,会话被自动关闭,说明其使用了with处理之后丧失了会话保持的能力。

那么我们在来看看Session类的内部是怎么实现with上下文的。

要想把一个类通过with关键字调用,那么类的内部,一定有__init__,__enter__,__exit__,这三个方法。

打开Session的源码,我们一起看看。

class Session(SessionRedirectMixin):
    """A Requests session.

    Provides cookie persistence, connection-pooling, and configuration.

    Basic Usage::

      >>> import requests
      >>> s = requests.Session()
      >>> s.get('https://httpbin.org/get')
      <Response [200]>

    Or as a context manager::

      >>> with requests.Session() as s:
      ...     s.get('https://httpbin.org/get')
      <Response [200]>
    """

    __attrs__ = [
        'headers', 'cookies', 'auth', 'proxies', 'hooks', 'params', 'verify',
        'cert', 'adapters', 'stream', 'trust_env',
        'max_redirects',
    ]

    def __init__(self):

        #: A case-insensitive dictionary of headers to be sent on each
        #: :class:`Request <Request>` sent from this
        #: :class:`Session <Session>`.
        self.headers = default_headers()

        #: Default Authentication tuple or object to attach to
        #: :class:`Request <Request>`.
        self.auth = None

        #: Dictionary mapping protocol or protocol and host to the URL of the proxy
        #: (e.g. {'http': 'foo.bar:3128', 'http://host.name': 'foo.bar:4012'}) to
        #: be used on each :class:`Request <Request>`.
        self.proxies = {}

        #: Event-handling hooks.
        self.hooks = default_hooks()

        #: Dictionary of querystring data to attach to each
        #: :class:`Request <Request>`. The dictionary values may be lists for
        #: representing multivalued query parameters.
        self.params = {}

        #: Stream response content default.
        self.stream = False

        #: SSL Verification default.
        self.verify = True

        #: SSL client certificate default, if String, path to ssl client
        #: cert file (.pem). If Tuple, ('cert', 'key') pair.
        self.cert = None

        #: Maximum number of redirects allowed. If the request exceeds this
        #: limit, a :class:`TooManyRedirects` exception is raised.
        #: This defaults to requests.models.DEFAULT_REDIRECT_LIMIT, which is
        #: 30.
        self.max_redirects = DEFAULT_REDIRECT_LIMIT

        #: Trust environment settings for proxy configuration, default
        #: authentication and similar.
        self.trust_env = True

        #: A CookieJar containing all currently outstanding cookies set on this
        #: session. By default it is a
        #: :class:`RequestsCookieJar <requests.cookies.RequestsCookieJar>`, but
        #: may be any other ``cookielib.CookieJar`` compatible object.
        self.cookies = cookiejar_from_dict({})

        # Default connection adapters.
        self.adapters = OrderedDict()
        self.mount('https://', HTTPAdapter())
        self.mount('http://', HTTPAdapter())

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

这个里面就实现了一套with关键字操作,可以看到的__exit__就实现了清理的操作。这样每次请求之后的会话记录就被清除了。

所以我们要想保持会话记录,可以直接使用Session进行请求,这样在不关闭python解释器的情况下每次请求的会话会一直被保持。

至于close里面的实现,目前我也只能看一个大概,里面的整体逻辑还是挺复杂的,为了不误人子弟,这里我就不再讲解了。大佬们可以自己去看看。

封装requests

requests库已经很好用了,但是我们在这个基础上还是要进行一层封装,为什么要封装呢。

首先,封装可以更好的去集成到测试框架中,减少我们的代码数量,并且我们只要要通过封装的类实例化一次session会话,不用担心会话重复的问题。在者我们可以和测试框架的其他模块进行耦合,所以在这种前提下,封装requests必不可少,即使他已经足够好用了。

以下是我的一个封装示例。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import urllib3
import requests

urllib3.disable_warnings()

http_method_names = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options']


class HttpRequest(object):
    """requests方法二次封装"""

    def __init__(self):
        self.timer = None
        self.timeout = 30.0
        self.session = requests.session()

    def request(self, method: str, url: str, **kwargs):
        """发送请求"""
        method = method.lower()

        def dispatch(method, *args, **kwargs):
            if method in http_method_names:
                handler = getattr(self.session, method)
                return handler(*args, **kwargs)
            else:
                raise AttributeError("请求方法不正确!")

        response = dispatch(method, url, **kwargs)
        self.timer = response.elapsed.total_seconds()
        return response

    def __call__(self, *args, **kwargs):
        """发送request请求"""
        return self.request(*args, **kwargs)


req = HttpRequest()

if __name__ == '__main__':
    r = req("get", url="https://www.baidu.com")
    print(r.text)
    print(req.timer)

运行一下:

requests的封装方式仁者见仁智者见智,每个人都有不一样的思想,不能因为看到了别人的封装形式就限制住了自己的思维,一定要有自己的想法,可以集百家之长处,但不可浑然无己见。所以在使用这个库的时候希望我们都能在工作或学习中发挥出他的妙用。

 

 好了 学习也就到此结束了 ,三连支持一下吧。

想了解更多相关知识请关注我吧!衷心感谢每一个认真阅读我文章的人!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/435428.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TiDB实战篇-数据导出工具Dumpling

简介 简要使用数据导出工具。 介绍 特点 适用场景 部署 下载 TiDB 社区版 | PingCAP 安装 #解压下载好的安装包 tar -zxvf tidb-community-toolkit-v6.5.0-linux-amd64.tar.gz #进入到文件夹以后解压出dumpling cd tidb-community-toolkit-v6.5.0-linux-amd64 tar -zxvf d…

MySQL中的索引index(超详细)

概念&#xff1a; 在MySQL中&#xff0c;索引&#xff08;index&#xff09;是一种特殊的数据结构&#xff0c;它能够加快数据库中数据的检索速度。索引可以看做是一本书的目录&#xff0c;它提供了一种快速查找数据的方式。 MySQL中的索引是建立在一张表的一列或多列上的&…

开发者社区项目开发流程

项目流程&#xff1a; 项目创建 首先创建一个文件夹&#xff0c;然后找到要创建项目的文件夹 输入CMD 进入小黑窗 输入“vue create 项目名” 创建我们这个项目(其中细节Ctrl左键点击链接见个人博客(99条消息) 创建Vue项目流程_啊唯11的博客-CSDN博客) 2.删除项认文件&#x…

C++命名空间域namespace与域作用限制符: :,cin,cout输入输出简单介绍

TIPS C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式等C总计63个关键字&#xff0c;C语言32个关键字&#xff0c;具体没有必要先不去管它 域&#xff0c;命名空间域与namespace关键字 cpp需要解决的第一…

Java后端面试题 重难点和被问到没答上来的点(包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue等)

以下是我记录的一些重点问题和面试中被问到没答上来的问题&#xff0c;包括java基础、关系型数据库、Redis、计算机网络、Spring、Java多线程、vue 问题目录 1.fail-safe和fail-fast2.四引用3.explain字段重要内容4.maven三大生命周期5.MYSQL 创建修改表6.数据库三范式7.Strin…

华科超算用户手册的学习笔记

1. 资源计费 1.1 费用记账 日期费用&#xff08;上限3000元&#xff09;2023.04.171002023.04.18200总计300 1.2 创建实例时显示项目的余额不足 这是因为项目账户之中目前还没有足够的卡时&#xff1b; Note 这里是因为上次充值的卡时还在田老师的个人账户中&#xff0c;还需…

vue el-table 单机行选中高亮并获取行数据,再次单击取消行选中

1. 效果展示 当没有行被选中时&#xff0c;按钮是不可用的 当有行被选中时&#xff0c;该行高亮&#xff0c;同时按钮可用 再次点击该行&#xff0c;取消高亮&#xff0c;按钮不可用 2. 代码 2.1 组件代码 table设置了highlight-current-row&#xff0c;可以在选中某个数据行…

List集合和Set集合的区别

Collection集合总结 在进行Java开发的时候经常会用到集合&#xff0c;而集合又主要分为两种&#xff1a;Collection单列集合和Map集合。这里主要介绍一下Collection的一些常用子接口的区别。 Collection集合&#x1f62e; 指单列集合&#xff0c;存储的一组对象。 List&#x…

4大方法,教你如何做好项目管理

作为一个项目经理&#xff0c;项目管理是我们日常工作最核心的一项职能。无论是公司的业务开发还是重大项目的推进&#xff0c;都离不开项目管理。然而对于很多初入职场的人来说&#xff0c;项目管理还是一个相当新颖、陌生的领域&#xff0c;因此我今天就来分享一些我在项目管…

【安全与风险】密码安全和用户认证

密码安全和用户认证 基本问题证明你是谁为什么要验证还需要什么基于口令的身份认证常用使用模式常用使用模式可惜的是社会工程悉尼大学 (绿化96)尴尬和记忆关于密码使用的3个主要问题UNIX形式的密码密码散列字典式攻击影子密码其他密码问题生物计量学多模式生物识别系统定义为什…

数字化体验时代,企业如何做好内部知识数字化管理

随着数字化时代的到来&#xff0c;企业内部的知识管理也面临着新的挑战和机遇。数字化技术的应用&#xff0c;可以极大地提高企业内部知识的数字化管理效率和质量&#xff0c;从而提升企业内部的工作效率、员工满意度和企业竞争力。本文将从数字化时代的背景出发&#xff0c;探…

NVM安装nodejs的方法

前提&#xff1a; 为解决nodejs升级后出现的各种问题&#xff0c;使用NVM在一台电脑上安装多个版本的nodejs&#xff0c;以便项目可以根据自身使用的node版本来开发。 nodejs版本的查询地址&#xff1a; https://nodejs.org/zh-cn/download/releases/ nodejs下载官网地址&…

17.样式冲突

写在 .vue 组件中的样式会全局生效&#xff0c;比如我现在有一个LEFT组件 有一个RIGHT组件 将LEFT组件与RIGHT组件放在App组件中 发现我只给LEFT样式&#xff0c;但是在RIGHT中也生效了 为了避免这种情况&#xff0c;我们有下面几种解决方式 目录 1 具体到指定的标签 2 sc…

【微信小程序-原生开发】实用教程22 - 绘制图表(引入 echarts,含图表的懒加载-获取到数据后再渲染图表,多图表加载等技巧)

最终效果预览 实现流程 微信小程序中使用 echarts 需使用官方提供的 ec-canvas 组件 1. 下载 ec-canvas 组件 点击下方链接&#xff0c;下载 ec-canvas 组件 https://gitcode.net/mirrors/ecomfe/echarts-for-weixin/-/tree/master 将其中的 ec-canvas 文件夹拷贝到微信小程序…

数据结构考研版——用栈实现后缀表达式前缀表达式求值

用栈实现后缀表达式求值 int calsub(float opand1,char op,float opand2,float &result) {if(op){resultopand1opand2;}if(op-){resultopand1-opand2;}if(op*){resultopand1*opand2;}if(op/){//判断是否为0一般把它与我们宏定义的极小值值进行比较&#xff0c;接近于0则视…

把你的阿里巴巴图标库转成你自己的@ant-design/icons

背景 我们使用iconfont-阿里巴巴矢量图标库来管理自己的一套图标&#xff0c;并且基于它的js资源&#xff0c;封装了自己的icons图标组件。封装的方法是使用了antd提供的createFromIconfontCN方法 但随着图标库越来越大&#xff0c;JS资源文件也变得越来越大。在业务中&#x…

protobuf序列化原理、安装与应用

目录 protobuf序列化 protobuf的原理 protobuf 的安装 编译message文件 应用protobuf protobuf序列化 protobuf是一种比json和xml等序列化工具更加轻量和高效的结构化数据存储格式&#xff0c;性能比json和xml真的强很多&#xff0c;毕竟google出品。 官网&#xff1a;https:…

C语言笔记 | 一元三次方程

文章目录 0x00 前言 0x01 问题分析 0x02 代码设计 0x03 完整代码 0x04 运行效果 0x05 参考文献 0x06 总结 0x00 前言 在 1545 年&#xff0c;意大利学者卡丹所写的《关于代数的大法》中&#xff0c;提出了一元三次方程的求根公式。人们将其称为卡丹公式。对于标准型的一…

Python 彩蛋 —— 开发人员留下的惊喜

Python 彩蛋 —— 开发人员留下的惊喜 简介&#xff1a;Python 核心程序开发人员在软件内部设计了2个彩蛋。一起来看看吧。 文章目录 Python 彩蛋 —— 开发人员留下的惊喜&#x1f4a1;彩蛋一&#xff1a;Python 之禅&#x1f4a1;彩蛋二&#xff1a;Python 有趣的漫画 &#…

程序员面试完之后,人麻了...

去面试吧 面不被录用的试 面hr为了完成任务的试 面一轮二轮没有下文试 面需要通勤2小时的试 面随时加班的试 ...... 今年的“金三银四”被网友们称为“铜三铁四”&#xff0c;招聘软件上的岗位都能背下来了&#xff0c;简历却依然石沉大海。 好不容易等来个回复&#xff…