39、Python模块、包管理及网络编程实用指南

Python模块、包管理及网络编程实用指南

在Python编程中,模块和包的管理以及网络编程是非常重要的部分。下面将详细介绍相关的知识和操作方法。

模块与包的操作
读取包内数据文件

假设有一个名为 mypackage 的包,其文件结构如下:

mypackage/ 
    __init__.py 
    somedata.dat 
    spam.py

spam.py 文件想要读取 somedata.dat 文件的内容,可以使用以下代码:

# spam.py 
import pkgutil 
data = pkgutil.get_data(__package__, 'somedata.dat')

这里得到的 data 变量是一个包含未处理文件内容的字节串。使用 pkgutil.get_data() 函数的好处是,它是一个高级工具,无论包安装在哪里或如何安装,都能获取文件数据。该函数的第一个参数是包含包名的字符串,可以直接提供,也可以使用特殊变量 __package__ ;第二个参数是包内文件的相对名称。

向sys.path添加目录

当Python代码因不在 sys.path 列出的目录中而无法导入时,可以通过以下两种常见方法向 sys.path 添加新目录:
- 通过环境变量PYTHONPATH

bash % env PYTHONPATH=/some/dir:/other/dir python3 

在自己的应用程序中,可以在程序启动时或通过脚本修改这个环境变量。
- 创建.pth文件
创建一个名为 myapplication.pth 的文件,内容如下:

/some/dir 
/other/dir

将这个文件放在Python的 site-packages 目录之一,如 /usr/local/lib/python3.3/site-packages ~/.local/lib/python3.3/site-packages 。解释器启动时,文件中列出的目录会被添加到 sys.path 中。

不建议手动修改 sys.path 的值,因为这会使代码变得脆弱,难以维护。例如:

import sys 
sys.path.insert(0, '/some/dir') 
sys.path.insert(0, '/other/dir')

不过,可以使用模块级变量 __file__ 来构造合适的绝对路径,避免硬编码目录名:

import sys 
from os.path import abspath, join, dirname 
sys.path.insert(0, abspath(dirname('__file__'), 'src'))
以字符串形式导入模块

如果有一个模块名存储在字符串中,想要导入该模块,可以使用 importlib.import_module() 函数。例如:

import importlib 
math = importlib.import_module('math') 
math.sin(2) 
mod = importlib.import_module('urllib.request') 
u = mod.urlopen('http://www.python.org') 

对于包, import_module() 也可用于相对导入,但需要提供额外的参数:

import importlib 
# 等同于 'from . import b' 
b = importlib.import_module('.b', __package__)
从远程计算机加载模块

要使Python的导入指令能够透明地从远程计算机加载模块,可以通过以下两种方法实现:
- 创建显式加载函数

import imp 
import urllib.request 
import sys 

def load_module(url): 
    u = urllib.request.urlopen(url) 
    source = u.read().decode('utf-8') 
    mod = sys.modules.setdefault(url, imp.new_module(url)) 
    code = compile(source, url, 'exec') 
    mod.__file__ = url 
    mod.__package__ = '' 
    exec(code, mod.__dict__) 
    return mod

使用示例:

fib = load_module('http://localhost:15000/fib.py') 
fib.fib(10) 
spam = load_module('http://localhost:15000/spam.py') 
spam.hello('Guido') 

这种方法适用于简单模块,但对于更复杂的结构(如包),需要额外的工作。
- 创建自定义导入器
可以编写“元路径导入器”,示例代码如下:

# urlimport.py 
import sys 
import importlib.abc 
import imp 
from urllib.request import urlopen 
from urllib.error import HTTPError, URLError 
from html.parser import HTMLParser 
import logging 
log = logging.getLogger(__name__) 

# 获取链接 
def _get_links(url): 
    class LinkParser(HTMLParser): 
        def handle_starttag(self, tag, attrs):   
            if tag == 'a': 
                attrs = dict(attrs) 
                links.add(attrs.get('href').rstrip('/')) 
    links = set() 
    try: 
        log.debug('Getting links from %s' % url) 
        u = urlopen(url) 
        parser = LinkParser() 
        parser.feed(u.read().decode('utf-8')) 
    except Exception as e: 
        log.debug('Could not get links. %s', e) 
    log.debug('links: %r', links) 
    return links 

class UrlMetaFinder(importlib.abc.MetaPathFinder): 
    def __init__(self, baseurl): 
        self._baseurl = baseurl 
        self._links = { } 
        self._loaders = { baseurl : UrlModuleLoader(baseurl) } 

    def find_module(self, fullname, path=None): 
        log.debug('find_module: fullname=%r, path=%r', fullname, path) 
        if path is None: 
            baseurl = self._baseurl 
        else: 
            if not path[0].startswith(self._baseurl): 
                return None 
            baseurl = path[0] 

        parts = fullname.split('.') 
        basename = parts[-1] 
        log.debug('find_module: baseurl=%r, basename=%r', baseurl, basename) 

        # 检查链接缓存 
        if basename not in self._links: 
            self._links[baseurl] = _get_links(baseurl) 

        # 检查是否为包 
        if basename in self._links[baseurl]: 
            log.debug('find_module: trying package %r', fullname) 
            fullurl = self._baseurl + '/' + basename 
            # 尝试加载包 
            loader = UrlPackageLoader(fullurl) 
            try: 
                loader.load_module(fullname) 
                self._links[fullurl] = _get_links(fullurl) 
                self._loaders[fullurl] = UrlModuleLoader(fullurl) 
                log.debug('find_module: package %r loaded', fullname) 
            except ImportError as e: 
                log.debug('find_module: package failed. %s', e) 
                loader = None 
            return loader 

        # 普通模块 
        filename = basename + '.py' 
        if filename in self._links[baseurl]: 
            log.debug('find_module: module %r found', fullname) 
            return self._loaders[baseurl] 
        else: 
            log.debug('find_module: module %r not found', fullname) 
            return None 

    def invalidate_caches(self): 
        log.debug('invalidating link cache') 
        self._links.clear() 

class UrlModuleLoader(importlib.abc.SourceLoader): 
    def __init__(self, baseurl): 
        self._baseurl = baseurl 
        self._source_cache = {} 

    def module_repr(self, module): 
        return '<urlmodule %r from %r>' % (module.__name__, module.__file__) 

    # 必需方法 
    def load_module(self, fullname): 
        code = self.get_code(fullname) 
        mod = sys.modules.setdefault(fullname, imp.new_module(fullname)) 
        mod.__file__ = self.get_filename(fullname) 
        mod.__loader__ = self 
        mod.__package__ = fullname.rpartition('.')[0] 
        exec(code, mod.__dict__) 
        return mod 

    # 可选扩展 
    def get_code(self, fullname): 
        src = self.get_source(fullname) 
        return compile(src, self.get_filename(fullname), 'exec') 

    def get_data(self, path): 
        pass 

    def get_filename(self, fullname): 
        return self._baseurl + '/' + fullname.split('.')[-1] + '.py' 

    def get_source(self, fullname): 
        filename = self.get_filename(fullname) 
        log.debug('loader: reading %r', filename) 
        if filename in self._source_cache: 
            log.debug('loader: cached %r', filename) 
            return self._source_cache[filename] 
        try: 
            u = urlopen(filename) 
            source = u.read().decode('utf-8') 
            log.debug('loader: %r loaded', filename) 
            self._source_cache[filename] = source 
            return source 
        except (HTTPError, URLError) as e: 
            log.debug('loader: %r failed. %s', filename, e) 
            raise ImportError("Can't load %s" % filename)    

    def is_package(self, fullname): 
        return False 

class UrlPackageLoader(UrlModuleLoader): 
    def load_module(self, fullname): 
        mod = super().load_module(fullname) 
        mod.__path__ = [ self._baseurl ] 
        mod.__package__ = fullname 

    def get_filename(self, fullname): 
        return self._baseurl + '/' + '__init__.py' 

    def is_package(self, fullname): 
        return True 

# 安装/卸载加载器的辅助函数 
_installed_meta_cache = { } 
def install_meta(address): 
    if address not in _installed_meta_cache: 
        finder = UrlMetaFinder(address) 
        _installed_meta_cache[address] = finder 
        sys.meta_path.append(finder) 
        log.debug('%r installed on sys.meta_path', finder) 

def remove_meta(address): 
    if address in _installed_meta_cache: 
        finder = _installed_meta_cache.pop(address) 
        sys.meta_path.remove(finder) 
        log.debug('%r removed from sys.meta_path', finder)

使用示例:

# 初始导入失败 
import fib 
# 加载导入器并再次尝试 
import urlimport 
urlimport.install_meta('http://localhost:15000') 
import fib 
import spam 
import grok.blah 

这种方法中, UrlMetaFinder 实例作为“最后机会的导入器”,当模块在常规位置未找到时会被调用。它会根据提供的URL构建有效链接集合,当导入模块时,将模块名与这些已知链接进行比较,若匹配则使用 UrlModuleLoader 加载模块。链接会被缓存,以避免重复的HTTP请求。

还可以编写直接附加到 sys.path 的钩子,示例代码如下:

# urlimport.py 
# ... 包含前面的代码 ... 

class UrlPathFinder(importlib.abc.PathEntryFinder): 
    def __init__(self, baseurl): 
        self._links = None 
        self._loader = UrlModuleLoader(baseurl) 
        self._baseurl = baseurl 

    def find_loader(self, fullname): 
        log.debug('find_loader: %r', fullname) 
        parts = fullname.split('.') 
        basename = parts[-1] 
        # 检查链接缓存 
        if self._links is None: 
            self._links = [] 
            self._links = _get_links(self._baseurl) 

        # 检查是否为包 
        if basename in self._links: 
            log.debug('find_loader: trying package %r', fullname) 
            fullurl = self._baseurl + '/' + basename 
            # 尝试加载包 
            loader = UrlPackageLoader(fullurl) 
            try: 
                loader.load_module(fullname) 
                log.debug('find_loader: package %r loaded', fullname) 
            except ImportError as e: 
                log.debug('find_loader: %r is a namespace package', fullname) 
                loader = None 
            return (loader, [fullurl]) 

        # 普通模块 
        filename = basename + '.py' 
        if filename in self._links: 
            log.debug('find_loader: module %r found', fullname) 
            return (self._loader, []) 
        else: 
            log.debug('find_loader: module %r not found', fullname) 
            return (None, []) 

    def invalidate_caches(self): 
        log.debug('invalidating link cache') 
        self._links = None 

# 检查路径是否为URL 
_url_path_cache = {} 
def handle_url(path): 
    if path.startswith(('http://', 'https://')): 
        log.debug('Handle path? %s. [Yes]', path) 
        if path in _url_path_cache: 
            finder = _url_path_cache[path] 
        else: 
            finder = UrlPathFinder(path) 
            _url_path_cache[path] = finder 
        return finder 
    else: 
        log.debug('Handle path? %s. [No]', path) 

def install_path_hook(): 
    sys.path_hooks.append(handle_url) 
    sys.path_importer_cache.clear() 
    log.debug('Installing handle_url') 

def remove_path_hook(): 
    sys.path_hooks.remove(handle_url) 
    sys.path_importer_cache.clear() 
    log.debug('Removing handle_url')

使用示例:

# 初始导入失败 
import fib 
# 安装路径钩子 
import urlimport 
urlimport.install_path_hook() 
# 导入仍然失败(不在路径中) 
import fib 
# 添加记录到sys.path 
import sys 
sys.path.append('http://localhost:15000') 
import fib 
import grok.blah 
导入模块时应用更改

若想在模块导入并被使用时更改模块中的函数或应用装饰器,可以使用以下方法:

# postimport.py 
import importlib 
import sys 
from collections import defaultdict 

_post_import_hooks = defaultdict(list) 

class PostImportFinder: 
    def __init__(self): 
        self._skip = set() 

    def find_module(self, fullname, path=None): 
        if fullname in self._skip: 
            return None 
        self._skip.add(fullname) 
        return PostImportLoader(self) 

class PostImportLoader: 
    def __init__(self, finder): 
        self._finder = finder 

    def load_module(self, fullname): 
        importlib.import_module(fullname) 
        module = sys.modules[fullname] 
        for func in _post_import_hooks[fullname]: 
            func(module) 
        self._finder._skip.remove(fullname) 
        return module 

def when_imported(fullname): 
    def decorate(func): 
        if fullname in sys.modules: 
            func(sys.modules[fullname]) 
        else: 
            _post_import_hooks[fullname].append(func) 
        return func 
    return decorate 

sys.meta_path.insert(0, PostImportFinder())

使用示例:

from postimport import when_imported 
@when_imported('threading') 
def warn_threads(mod): 
    print('Threads? Are you crazy?') 
import threading 

更实际的例子是对现有定义应用装饰器:

from functools import wraps 
from postimport import when_imported 

def logged(func): 
    @wraps(func) 
    def wrapper(*args, **kwargs): 
        print('Calling', func.__name__, args, kwargs) 
        return func(*args, **kwargs) 
    return wrapper 

# 示例 
@when_imported('math') 
def add_logging(mod): 
    mod.cos = logged(mod.cos) 
    mod.sin = logged(mod.sin)
包的安装与分发
为自己安装包

当没有权限将包安装到系统Python中,或只想为自己安装包时,可以使用以下命令:

python3 setup.py install --user

pip install --user packagename

用户特定的 site-packages 目录通常在 sys.path 中位于系统 site-packages 目录之前,因此使用此方法安装的包具有优先级。

创建新的Python环境

可以使用 pyvenv 命令创建新的“虚拟”环境:

bash % pyvenv Spam 

创建后的 Spam 目录结构如下:

bin     include     lib     pyvenv.cfg 

bin 目录中可以找到Python解释器:

bash % Spam/bin/python3 

虚拟环境的主要特点是其 site-packages 目录被设置为新环境,安装的第三方包将安装在此处,而不是系统的 site-packages 目录。默认情况下,虚拟环境是干净的,不包含第三方包。若想包含已安装的包,可以使用 --system-site-packages 选项创建:

bash % pyvenv --system-site-packages Spam 
分发包

若想将自己编写的库分发给他人,首先要为其分配一个唯一的名称并清理目录结构。例如,一个典型的包结构如下:

projectname/ 
    README.txt 
    Doc/ 
        documentation.txt 
    projectname/ 
        __init__.py 
        foo.py 
        bar.py 
        utils/ 
            __init__.py 
            spam.py 
            grok.py 
    examples/ 
        helloworld.py 
        ...

然后编写 setup.py 文件:

# setup.py 
from distutils.core import setup 

setup(name='projectname', 
      version='1.0', 
      author='Your Name', 
      author_email='you@youraddress.com', 
      url='http://www.you.com/projectname', 
      packages=['projectname', 'projectname.utils'], 
)

再创建 MANIFEST.in 文件,列出不包含源代码但想包含在包中的文件:

# MANIFEST.in 
include *.txt 
recursive-include examples * 
recursive-include Doc *

确保 setup.py MANIFEST.in 位于包的最高级目录。然后运行以下命令创建分发源:

% bash python3 setup.py sdist

这将创建 projectname-1.0.zip projectname-1.0.tar.gz 文件,可以将其分发给他人或上传到Python Package Index。

网络编程:与HTTP服务交互

在Python中,作为客户端与各种Web服务进行HTTP交互有多种方法。

使用urllib.request进行简单请求

对于简单任务, urllib.request 模块通常就足够了。
- 发送GET请求

from urllib import request, parse 

# 基础URL 
url = 'http://httpbin.org/get' 

# 请求参数 
parms = { 
    'name1' : 'value1', 
    'name2' : 'value2' 
} 

# 编码查询字符串 
querystring = parse.urlencode(parms) 

# 发送GET请求并读取响应 
u = request.urlopen(url + '?' + querystring) 
resp = u.read()
  • 发送POST请求
from urllib import request, parse 

# 基础URL 
url = 'http://httpbin.org/post' 

# 请求参数 
parms = { 
    'name1' : 'value1', 
    'name2' : 'value2' 
} 

# 编码查询字符串 
querystring = parse.urlencode(parms) 

# 发送POST请求并读取响应 
u = request.urlopen(url, querystring.encode('ascii')) 
resp = u.read()
  • 提供自定义HTTP头
from urllib import request, parse 

# 基础URL 
url = 'http://httpbin.org/post' 

# 请求参数 
parms = { 
    'name1' : 'value1', 
    'name2' : 'value2' 
} 

# 编码查询字符串 
querystring = parse.urlencode(parms) 

# 额外的头信息 
headers = { 
    'User-agent' : 'none/ofyourbusiness', 
    'Spam' : 'Eggs' 
} 

req = request.Request(url, querystring.encode('ascii'), headers=headers) 

# 发送请求并读取响应 
u = request.urlopen(req) 
resp = u.read()
使用requests库进行复杂交互

如果与服务的交互更复杂, requests 库是更好的选择。
- 发送POST请求

import requests 

# 基础URL 
url = 'http://httpbin.org/post' 

# 请求参数 
parms = { 
    'name1' : 'value1', 
    'name2' : 'value2' 
} 

# 额外的头信息 
headers = { 
    'User-agent' : 'none/ofyourbusiness', 
    'Spam' : 'Eggs' 
} 

resp = requests.post(url, data=parms, headers=headers) 

# 解码后的响应文本 
text = resp.text
  • 发送HEAD请求并提取头信息
import requests 

resp = requests.head('http://www.python.org/index.html') 

status = resp.status_code 
last_modified = resp.headers['last-modified'] 
content_type = resp.headers['content-type'] 
content_length = resp.headers['content-length']
  • 使用基本认证登录
import requests 
resp = requests.get('http://pypi.python.org/pypi?:action=login', 
                     auth=('user','password'))
  • 传递HTTP Cookie
import requests 

# 第一个请求 
resp1 = requests.get(url) 

# 第二个请求,使用第一个请求的Cookie 
resp2 = requests.get(url, cookies=resp1.cookies)
  • 上传数据到服务器
import requests 
url = 'http://httpbin.org/post' 
files = { 'file': ('data.csv', open('data.csv', 'rb')) } 

r = requests.post(url, files=files)

在开发客户端HTTP代码时,测试可能会因为许多不明显的细节而变得困难。可以使用 httpbin 服务进行测试,它会以JSON响应的形式返回请求信息。例如:

import requests 
r = requests.get('http://httpbin.org/get?name=Dave&n=37')

综上所述,Python在模块和包管理以及网络编程方面提供了丰富的工具和方法,通过合理运用这些知识,可以更高效地进行Python编程。

Python模块、包管理及网络编程实用指南

模块与包操作的深入理解

在前面介绍了模块与包的各种操作方法,这里进一步深入探讨其中的一些关键概念和细节。

模块缓存机制

Python解释器会对模块进行缓存,缓存的模块可以在 sys.modules 字典中找到。这意味着,如果一个模块已经被导入过,再次导入时不会重新加载,而是直接使用缓存中的模块。例如:

import sys
import imp

# 尝试从缓存中获取模块,如果不存在则创建新模块
m = sys.modules.setdefault('spam', imp.new_module('spam'))
print(m)

这种缓存机制可以提高模块导入的效率,但在某些情况下可能会导致问题,比如在开发过程中修改了模块代码,需要重新加载模块时,就需要手动处理缓存。

包的处理细节

在处理包时,需要特别注意 __init__.py 文件的作用。 __init__.py 文件可以为空,也可以包含初始化代码,它的存在告诉Python该目录是一个包。当导入一个包时, __init__.py 文件会被执行。例如:

my_package/
    __init__.py
    module1.py
    module2.py

在导入 my_package 时, __init__.py 会被执行:

import my_package

另外,在处理包的子模块时,需要正确设置 __path__ 属性。 __path__ 属性是一个列表,包含了包的搜索路径。例如,在自定义的 UrlPackageLoader 类中,就需要设置 __path__ 属性:

class UrlPackageLoader(UrlModuleLoader):
    def load_module(self, fullname):
        mod = super().load_module(fullname)
        mod.__path__ = [ self._baseurl ]
        mod.__package__ = fullname
        return mod
导入钩子机制的原理与应用

导入钩子机制是Python中一个强大的特性,它允许我们自定义模块的导入过程。在前面介绍了两种导入钩子的实现方法,下面详细分析其原理和应用场景。

元路径导入器的原理

元路径导入器是通过修改 sys.meta_path 列表来实现的。 sys.meta_path 是一个包含元路径查找器的列表,当Python解释器执行 import 语句时,会依次调用 sys.meta_path 中的查找器的 find_module 方法,直到找到合适的加载器。例如,在自定义的 UrlMetaFinder 类中:

class UrlMetaFinder(importlib.abc.MetaPathFinder):
    def __init__(self, baseurl):
        self._baseurl = baseurl
        self._links = { }
        self._loaders = { baseurl : UrlModuleLoader(baseurl) }

    def find_module(self, fullname, path=None):
        # 查找模块的逻辑
        pass

import 语句执行时,解释器会调用 UrlMetaFinder find_module 方法,根据模块名和路径查找合适的加载器。

路径钩子的原理

路径钩子是通过修改 sys.path_hooks 列表来实现的。 sys.path_hooks 是一个包含路径查找函数的列表,当Python解释器处理 sys.path 中的每个目录时,会依次调用 sys.path_hooks 中的函数,根据目录的特点返回合适的查找器。例如,在自定义的 handle_url 函数中:

def handle_url(path):
    if path.startswith(('http://', 'https://')):
        # 如果路径是URL,则返回UrlPathFinder查找器
        if path in _url_path_cache:
            finder = _url_path_cache[path]
        else:
            finder = UrlPathFinder(path)
            _url_path_cache[path] = finder
        return finder
    else:
        return None

当解释器处理 sys.path 中的目录时,如果目录是一个URL,就会调用 handle_url 函数,返回 UrlPathFinder 查找器。

导入钩子的应用场景

导入钩子可以用于很多场景,比如:
- 动态加载模块 :根据不同的条件动态加载不同的模块。
- 模块监控 :在模块导入时进行监控,记录日志或执行一些额外的操作。
- 模块替换 :用自定义的模块替换系统中的模块。

虚拟环境的管理与使用

虚拟环境是Python开发中非常重要的工具,它可以帮助我们隔离不同项目的依赖,避免版本冲突。

虚拟环境的创建与激活

使用 pyvenv 命令可以创建虚拟环境:

bash % pyvenv myenv

创建完成后,需要激活虚拟环境。在不同的操作系统中,激活虚拟环境的方法不同:
- Windows

myenv\Scripts\activate
  • Linux/Mac
source myenv/bin/activate

激活虚拟环境后,所有的Python命令和包安装都会在该虚拟环境中进行。

虚拟环境的管理

在虚拟环境中,可以使用 pip 命令安装和管理包。例如,安装 requests 包:

pip install requests

如果需要退出虚拟环境,可以使用 deactivate 命令:

deactivate

另外,还可以使用 --system-site-packages 选项创建虚拟环境,这样虚拟环境会包含系统中已经安装的包:

bash % pyvenv --system-site-packages myenv
网络编程的高级应用

在前面介绍了与HTTP服务交互的基本方法,下面介绍一些网络编程的高级应用。

异步HTTP请求

在处理大量的HTTP请求时,同步请求可能会导致性能问题。可以使用 asyncio aiohttp 库实现异步HTTP请求。例如:

import asyncio
import aiohttp

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, 'http://www.example.com')
        print(html)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

aiohttp 库提供了异步的HTTP客户端和服务器功能,可以大大提高网络请求的效率。

网络爬虫

网络爬虫是一种自动获取网页内容的程序。可以使用Python编写简单的网络爬虫。例如,爬取一个网页的标题:

import requests
from bs4 import BeautifulSoup

url = 'http://www.example.com'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
title = soup.title.string
print(title)

BeautifulSoup 库可以帮助我们解析HTML和XML文档,提取所需的信息。

总结与展望

Python在模块和包管理以及网络编程方面提供了丰富的工具和方法。通过合理运用这些知识,可以更高效地进行Python编程。在模块和包管理方面,我们可以灵活地读取包内数据文件、向 sys.path 添加目录、以字符串形式导入模块、从远程计算机加载模块等。在网络编程方面,我们可以使用 urllib.request requests 库与HTTP服务进行交互,还可以实现异步HTTP请求和网络爬虫等高级应用。

未来,随着Python的不断发展,模块和包管理以及网络编程的功能可能会更加完善和强大。例如,导入钩子机制可能会有更多的应用场景和优化,网络编程可能会支持更多的协议和功能。我们需要不断学习和探索,以跟上Python技术的发展步伐。

以下是网络编程中不同请求方式的对比表格:
| 请求方式 | 适用场景 | 代码示例 |
| ---- | ---- | ---- |
| GET | 获取资源 | python<br>from urllib import request, parse<br><br>url = 'http://httpbin.org/get'<br>parms = {<br> 'name1' : 'value1',<br> 'name2' : 'value2'<br>}<br>querystring = parse.urlencode(parms)<br>u = request.urlopen(url + '?' + querystring)<br>resp = u.read()<br> |
| POST | 提交数据 | python<br>from urllib import request, parse<br><br>url = 'http://httpbin.org/post'<br>parms = {<br> 'name1' : 'value1',<br> 'name2' : 'value2'<br>}<br>querystring = parse.urlencode(parms)<br>u = request.urlopen(url, querystring.encode('ascii'))<br>resp = u.read()<br> |
| HEAD | 获取资源元信息 | python<br>import requests<br><br>resp = requests.head('http://www.python.org/index.html')<br>status = resp.status_code<br>last_modified = resp.headers['last-modified']<br>content_type = resp.headers['content-type']<br>content_length = resp.headers['content-length']<br> |

以下是虚拟环境操作的流程图:

graph TD;
    A[创建虚拟环境] --> B[激活虚拟环境];
    B --> C[安装包];
    C --> D[使用包];
    D --> E[退出虚拟环境];

通过以上的学习和实践,相信大家对Python的模块和包管理以及网络编程有了更深入的理解和掌握。希望这些知识能够帮助大家在Python编程的道路上取得更好的成果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值