35、Python 数据持久化与命令行工具开发

Python 数据持久化与命令行工具开发

数据持久化工具介绍

在数据持久化方面,我们会用到不同的工具,它们各有特点,能满足不同场景的需求。

Storm 库的使用

Storm 库可用于数据的存储和检索。即使记录不是通过 Storm 库插入的,也能正常显示。例如,执行 python storm_retrieve_os.py 命令,会显示一条记录:

1 Linux 2.0.34 kernel

当运行添加脚本 python storm_add_os.py 后再运行检索脚本 python storm_retrieve_os.py ,会显示旧记录和新插入的记录:

1 Linux 2.0.34 kernel
2 Windows 3.1.1

若要对数据进行过滤,比如只查看以 “Lin” 开头的操作系统条目,可以使用以下代码:

import storm.locals
import storm_model
import os
db = storm.locals.create_database('sqlite:///%s' % os.path.join(os.getcwd(), 
  'inventory.db'))
store = storm.locals.Store(db)
for o in store.find(storm_model.OperatingSystem, 
  storm_model.OperatingSystem.name.like(u'Lin%')):
    print o.id, o.name, o.description

运行 python storm_retrieve_os_filter.py 后,输出结果如下:

1 Linux 2.0.34 kernel

数据库中虽有 “Windows 3.1.1” 条目,但因 “Windows” 不以 “Lin” 开头而被过滤掉。

SQLAlchemy ORM

目前,SQLAlchemy 似乎是 Python 中占主导地位的 ORM。它的方法与 Storm 类似,不过 SQLAlchemy 出现得更早。下面是 inventory_operatingsystem 表的定义和对象定义:

#!/usr/bin/env python
import os
from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, Text, VARCHAR, MetaData
from sqlalchemy.orm import mapper
from sqlalchemy.orm import sessionmaker
engine = create_engine('sqlite:///%s' % os.path.join(os.getcwd(), 
        'inventory.db'))
metadata = MetaData()
os_table = Table('inventory_operatingsystem', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', VARCHAR(50)),
    Column('description', Text()),
)
class OperatingSystem(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description
    def __repr__(self):
       return "<OperatingSystem('%s','%s')>" % (self.name, self.description)
mapper(OperatingSystem, os_table) 
Session = sessionmaker(bind=engine, autoflush=True, transactional=True)
session = Session()

与 Storm 示例表定义代码的最大区别在于,SQLAlchemy 使用了一个额外的类,并将两者进行映射。

查询表中所有记录的代码如下:

#!/usr/bin/env python
from sqlalchemy_inventory_definition import session, OperatingSystem
for os in session.query(OperatingSystem):
    print os

运行 python sqlalchemy_inventory_query_all.py 后,输出示例如下:

<OperatingSystem('Linux','2.0.34 kernel')>
<OperatingSystem('Windows','3.1.1')>

若要创建新记录,可通过实例化 OperatingSystem 对象并添加到会话中:

#!/usr/bin/env python
from sqlalchemy_inventory_definition import session, OperatingSystem
ubuntu_710 = OperatingSystem(name='Linux', description='2.6.22-14 kernel')
session.save(ubuntu_710)
session.commit()

再次运行查询所有记录的脚本,输出如下:

<OperatingSystem('Linux','2.0.34 kernel')>
<OperatingSystem('Windows','3.1.1')>
<OperatingSystem('Linux','2.6.22-14 kernel')>

过滤结果也很简单,例如过滤出名称以 “Lin” 开头的 OperatingSystem 记录,代码如下:

#!/usr/bin/env python
from sqlalchemy_inventory_definition import session, OperatingSystem
for os in session.query(OperatingSystem).filter(OperatingSystem.name.like('Lin%')):
    print os

运行 python sqlalchemy_inventory_query_filter.py 后,输出示例如下:

<OperatingSystem('Linux','2.0.34 kernel')>
<OperatingSystem('Linux','2.6.22-14 kernel')>
命令行工具开发基础

命令行对于系统管理员来说具有特殊意义,掌握命令行工具的创建是成为优秀系统管理员的关键。

基本标准输入使用

创建命令行工具的最简单方法是利用 sys 模块的 sys.argv 来处理命令行参数。以下是一个简单的命令行工具示例:

#!/usr/bin/env python
import sys
print sys.argv

执行不同命令的输出示例如下:
- ./sysargv.py 输出: ['./sysargv.py']
- ./sysargv.py foo 输出: ['./sysargv.py', 'test']
- ./sysargv.py foo bad for you 输出: ['./sysargv.py', 'foo', 'bad', 'for', 'you']

稍微修改代码,统计命令行参数的数量:

#!/usr/bin/env python
import sys
#Python indexes start at Zero, so let's not count the command itself which is
#sys.argv[0]
num_arguments = len(sys.argv) - 1
print sys.argv, "You typed in ", num_arguments, "arguments"

若要在没有传递参数时发送错误消息,可使用以下代码:

#!/usr/bin/env python
import sys
num_arguments = len(sys.argv) - 1
#If there are no arguments to the command, send a message to standard error.
if num_arguments == 0:
        sys.stderr.write('Hey, type in an option silly\n')
else:
        print sys.argv, "You typed in ", num_arguments, "arguments"

不过,使用 sys.argv 创建命令行工具虽然简单,但往往不是最佳选择。Python 标准库中的 optparse 模块能处理创建高质量命令行工具时的复杂问题。

Optparse 模块介绍

即使是小脚本,使用 optparse 处理选项也能带来很多好处。下面是一个 “Hello World” 示例:

#!/usr/bin/env python
import optparse
def main():
    p = optparse.OptionParser()
    p.add_option('--sysadmin', '-s', default="BOFH")
    options, arguments = p.parse_args()
    print 'Hello, %s' % options.sysadmin
if __name__ == '__main__':
    main()

运行该脚本的不同输出示例如下:
- python hello_world_optparse.py 输出: Hello, BOFH
- python hello_world_optparse.py --sysadmin Noah 输出: Hello, Noah
- python hello_world_optparse.py --s Jeremy 输出: Hello, Jeremy
- python hello_world_optparse.py --infinity Noah 会报错:

Usage: hello_world_optparse.py [options]
hello_world_optparse.py: error: no such option: --infinity

在这个小脚本中,我们可以设置短选项 -s 和长选项 --sysadmin ,以及默认值。同时, optparse 还提供了强大的内置错误处理功能。

Simple Optparse Usage Patterns
  • No Options Usage Pattern :即使不使用选项, optparse 也能发挥作用。以下是一个模仿 ls 命令的示例:
#!/usr/bin/env python
import optparse
import os
def main():
    p = optparse.OptionParser(description="Python  'ls' command clone",
                                prog="pyls",
                                version="0.1a",
                                usage="%prog [directory]")
    options, arguments = p.parse_args()
    if len(arguments) == 1:
        path = arguments[0]
        for filename in os.listdir(path):
            print filename
    else:
        p.print_help()
if __name__ == '__main__':
    main()

运行示例如下:
- python no_options.py . 输出当前目录下的文件列表。
- python no_options.py python no_options.py --help 会显示帮助信息。
- python no_options.py --version 会显示版本号。
- True/False Usage Pattern :使用选项设置程序中的布尔值很有用。例如,设置 --verbose 选项开启详细输出, --quiet 选项抑制输出。以下是示例代码:

#!/usr/bin/env python
import optparse
import os
def main():
    p = optparse.OptionParser(description="Python 'ls' command clone",
                                prog="pyls",
                                version="0.1a",
                                usage="%prog [directory]")
    p.add_option("--verbose", "-v", action="store_true",
                help="Enables Verbose Output",default=False)
    options, arguments = p.parse_args()
    if len(arguments) == 1:
        if options.verbose:
            print "Verbose Mode Enabled"
        path = arguments[0]
        for filename in os.listdir(path):
            if options.verbose:
                print "Filename: %s " % filename
            elif options.quiet:
                pass
            else:
                print filename
    else:
        p.print_help()
if __name__ == '__main__':
    main()

运行示例如下:
- python true_false.py /tmp 正常输出文件列表。
- python true_false.py --verbose /tmp 开启详细输出模式。

下面是使用 optparse 不同模式的流程图:

graph TD;
    A[开始] --> B{选择模式};
    B -->|No Options| C[执行无选项模式];
    B -->|True/False| D[执行布尔值模式];
    C --> E[结束];
    D --> E;

通过以上介绍,我们了解了 Python 中数据持久化的工具使用以及命令行工具开发的基础知识,希望能帮助你更好地进行 Python 编程。

Python 数据持久化与命令行工具开发

Simple Optparse Usage Patterns(续)
  • Counting Options Usage Pattern :在典型的 Unix 命令行工具中,如 tcpdump ,多次指定 -v 选项可增加详细输出级别。在 optparse 中也能实现类似功能,通过对选项的指定次数进行计数。以下是示例代码:
#!/usr/bin/env python
import optparse
import os
def main():
    p = optparse.OptionParser(description="Python 'ls' command clone",
                                prog="pyls",
                                version="0.1a",
                                usage="%prog [directory]")
    p.add_option("-v", action="count", dest="verbose")
    options, arguments = p.parse_args()
    if len(arguments) == 1:
        if options.verbose:
            print "Verbose Mode Enabled at Level: %s" % options.verbose
        path = arguments[0]
        for filename in os.listdir(path):
            if options.verbose == 1:
                print "Filename: %s " % filename
            elif options.verbose ==2 :
                fullpath = os.path.join(path,filename)
                print "Filename: %s | Byte Size: %s" % (filename,
                                    os.path.getsize(fullpath))
            else:
                print filename
    else:
        p.print_help()
if __name__ == '__main__':
    main()

运行示例如下:
- 不指定 -v 选项,正常输出文件名。
- 指定一次 -v 选项( python verbosity_levels_count.py -v /tmp ),输出 “Filename:” 加上文件名。
- 指定两次 -v 选项( python verbosity_levels_count.py -vv /tmp ),输出文件名和字节大小:

Verbose Mode Enabled at Level: 2
Filename: .aksusb | Byte Size: 0
Filename: alm.log | Byte Size: 1403
Filename: amt.log | Byte Size: 3038
...
  • Choices Usage Pattern :有时候为选项提供几个固定的选择会更方便。例如,将 --verbose --quiet 选项合并为一个 --chatty 选项,用户只能从指定的几个选项中选择。以下是示例代码:
#!/usr/bin/env python
import optparse
import os
def main():
    p = optparse.OptionParser(description="Python 'ls' command clone",
                                prog="pyls",
                                version="0.1a",
                                usage="%prog [directory]")
    p.add_option("--chatty", "-c", action="store", type="choice",
                    dest="chatty",
                    choices=["normal", "verbose", "quiet"],
                    default="normal")
    options, arguments = p.parse_args()
    print options
    if len(arguments) == 1:
        if options.chatty == "verbose":
            print "Verbose Mode Enabled"
        path = arguments[0]
        for filename in os.listdir(path):
            if options.chatty == "verbose":
                print "Filename: %s " % filename
            elif options.chatty == "quiet":
                pass
            else:
                print filename
    else:
        p.print_help()
if __name__ == '__main__':
    main()

运行示例如下:
- 不提供选项值( python choices.py --chatty )会报错,提示需要参数。
- 提供错误的选项值( python choices.py --chatty=nuclear /tmp )会报错,提示可用的选项:

Usage: pyls [directory]
pyls: error: option --chatty: invalid choice: 'nuclear' (choose from 'normal', 
  'verbose', 'quiet')
- 提供正确的选项值(`python choices.py --chatty=verbose /tmp`)会按相应模式输出:
{'chatty': 'verbose'}
Verbose Mode Enabled
Filename: .aksusb 
Filename: alm.log 
...
- 使用 `--chatty=quiet` 选项(`python choices.py --chatty=quiet /tmp`)则不输出文件名。

以下是 optparse 不同使用模式的总结表格:
| 使用模式 | 描述 | 示例选项 |
| ---- | ---- | ---- |
| No Options Usage Pattern | 不使用选项,利用 optparse 处理程序流程 | 无 |
| True/False Usage Pattern | 使用选项设置布尔值,控制输出级别 | --verbose , --quiet |
| Counting Options Usage Pattern | 对选项的指定次数进行计数,实现不同级别的输出 | -v |
| Choices Usage Pattern | 为选项提供固定的选择,限制用户输入 | --chatty |

总结

在 Python 编程中,我们有多种工具可用于数据持久化,如 Storm 库和 SQLAlchemy ORM。Storm 库可方便地进行数据的存储、检索和过滤操作;SQLAlchemy 作为主流的 ORM,提供了强大的数据库操作功能,包括表定义、记录查询、创建和过滤等。

在命令行工具开发方面,虽然使用 sys.argv 可以简单地处理命令行参数,但 optparse 模块能更好地处理复杂的选项和参数,提供了多种使用模式,如无选项模式、布尔值模式、计数选项模式和选择模式等,大大提高了命令行工具的质量和易用性。

通过掌握这些数据持久化工具和命令行工具开发技巧,我们可以更高效地进行 Python 编程,满足不同场景下的需求。

下面是一个综合的流程图,展示了从数据持久化到命令行工具开发的整体流程:

graph LR;
    A[数据持久化] --> B{选择工具};
    B -->|Storm| C[使用 Storm 进行操作];
    B -->|SQLAlchemy| D[使用 SQLAlchemy 进行操作];
    E[命令行工具开发] --> F{选择参数处理方式};
    F -->|sys.argv| G[简单参数处理];
    F -->|optparse| H[复杂选项处理];
    C --> I[结束];
    D --> I;
    G --> I;
    H --> I;

希望这些知识能帮助你在 Python 编程的道路上更进一步,不断探索和实践,创造出更强大的程序和工具。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值