标签 Python 下的文章

我们在使用SQLAlchemy做数据的增删改查操作,我们是通过session对象来实现的。

  1. 构建session对象:所有和数据库的ORM操作都必须通过一个叫做session的会话对象来实现,通过以下代码来获取会话对象:

    from sqlalchemy.orm import sessionmaker
    
    engine = create_engine(DB_URI)
    session = sessionmaker(engine)()
  2. 添加对象:

    class User(Base):
        __tablename__ = 'user'
    
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50))
        age = Column(Integer)
    • 创建对象,也即创建一条数据:

      u = User(name='xiaoning',age=18,country='china')
    • 将这个对象添加到session会话对象中:

      session.add(u)
    • 将session中的对象做commit操作(提交):

      session.commit()
    • 一次性添加多条数据:

      u1 = User(name='xiaoning',age=19,country='china')
      u2 = User(name='boke',age=20,country='china')
      session.add_all([u1,u2])
      session.commit()
  3. 查找对象:

    # 查找某个模型对应的那个表中所有的数据:
    all_user = session.query(User).all()
    # 使用filter_by来做条件查询
    all_user = session.query(User).filter_by(name='xiaoning').all()
    # 使用filter来做条件查询
    all_user = session.query(User).filter(User.name=='xiaoning').all()
    # 使用get方法查找数据,get方法是根据id来查找的,只会返回一条数据或者None
    user = session.query(User).get(primary_key)
    # 使用first方法获取结果集中的第一条数据
    user = session.query(User).first()

    小编在下一篇文章中将详细讲解查询。

    SQLAlchemy中filter()和filter_by()的区别
    1、filter引用列名时,使用“类名.属性名”的方式,比较使用两个等号“==”
    2、filter_by引用列名时,使用“属性名”,比较使用一个等号“=”
    3、在使用多条件匹配的时候,filter需要借助sqlalchemy里的and_ ; 而filter_by不需要,直接把多个匹配条件写在一起
    4、在使用多条件匹配时,用到>=、>、<=、<的情况,貌似不能使用filter_by。可能是姿势不对
  4. 修改对象:首先从数据库中查找对象,然后将这条数据修改为你想要的数据,最后做commit操作就可以修改数据了。

    user = session.query(User).first()
    user.name = 'boke'
    session.commit()
  5. 删除对象:将需要删除的数据从数据库中查找出来,然后使用session.delete方法将这条数据从session中删除,最后做commit操作就可以了。

    user = session.query(User).first()
    session.delete(user)
    session.commit()

SQLAlchemy连接数据库

使用SQLALchemy去连接数据库,其实就是需要使用一些配置信息,然后将他们组合成满足条件的字符串:# dialect+driver://username:password@host:port/database

HOSTNAME = '' # 主机地址
PORT = '3306' # 端口号
DATABASE = '' # 数据库
USERNAME = '' # 数据库账号
PASSWORD = '' # 数据库密码
DB_URI = "mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8".format(username=USERNAME,password=PASSWORD,host=HOSTNAME,port=PORT,db=DATABASE) # 链接

然后使用create_engine创建一个引擎engine,然后再调用这个引擎的connect方法,就可以得到这个对象,然后就可以通过这个对象对数据库进行操作了:

engine = create_engine(DB_URI)

# 判断是否连接成功
conn = engine.connect()
result = conn.execute('select 1')
print(result.fetchone())

将ORM模型映射到数据库中,即创建表

  1. declarative_base根据engine创建一个ORM基类。

    from sqlalchemy.ext.declarative import declarative_base
    engine = create_engine(DB_URI)
    Base = declarative_base(engine)
  2. 用这个Base类作为基类来写自己的ORM类。要定义__tablename__类属性,来指定这个模型映射到数据库中的表名。

    class User(Base):
        __tablename__ = 'user'
  3. 创建属性来映射到表中的字段,所有需要映射到表中的属性都应该为Column类型:

    class User(Base):
        __tablename__ = 'user'
        # 2. 在这个ORM模型中创建一些属性,来跟表中的字段进行一一映射。这些属性必须是sqlalchemy给我们提供好的数据类型。
        id = Column(Integer,primary_key=True,autoincrement=True)
        name = Column(String(50))
        age = Column(Integer)
  4. 使用Base.metadata.create_all()来将模型映射到数据库中。
  5. 一旦使用Base.metadata.create_all()将模型映射到数据库中后,即使改变了模型的字段,也不会重新映射了。
  6. 可以使用Base.metadata.drop_all()将继承Base类的表从数据库中删除。

SQLAlchemy常用数据类型

  1. Integer:整形,映射到数据库中是int类型。
  2. Float:浮点类型,映射到数据库中是float类型。他占据的32位。
  3. Double:双精度浮点类型,映射到数据库中是double类型,占据64位。
  4. String:可变字符类型,映射到数据库中是varchar类型.
  5. Boolean:布尔类型,映射到数据库中的是tinyint类型。
  6. DECIMAL:定点类型。是专门为了解决浮点类型精度丢失的问题的。在存储钱相关的字段的时候建议大家都使用这个数据类型。并且这个类型使用的时候需要传递两个参数,第一个参数是用来标记这个字段总能能存储多少个数字,第二个参数表示小数点后有多少位。
  7. Enum:枚举类型。指定某个字段只能是枚举中指定的几个值,不能为其他值。在ORM模型中,使用Enum来作为枚举,示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        tag = Column(Enum("python",'flask','django'))

    在Python3中,已经内置了enum这个枚举的模块,我们也可以使用这个模块去定义相关的字段。示例代码如下:

    class TagEnum(enum.Enum):
        python = "python"
        flask = "flask"
        django = "django"
    
    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        tag = Column(Enum(TagEnum))
    
    article = Article(tag=TagEnum.flask)
  8. Date:存储时间,只能存储年月日。映射到数据库中是date类型。在Python代码中,可以使用datetime.date来指定。示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        create_time = Column(Date)
    
    article = Article(create_time=date(2017,10,10))
  9. DateTime:存储时间,可以存储年月日时分秒毫秒等。映射到数据库中也是datetime类型。在Python代码中,可以使用datetime.datetime来指定。示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        create_time = Column(DateTime)
    
    article = Article(create_time=datetime(2011,11,11,11,11,11))
  10. Time:存储时间,可以存储时分秒。映射到数据库中也是time类型。在Python代码中,可以使用datetime.time来至此那个。示例代码如下:

    class Article(Base):
        __tablename__ = 'article'
        id = Column(Integer,primary_key=True,autoincrement=True)
        create_time = Column(Time)
    
    article = Article(create_time=time(hour=11,minute=11,second=11))
  11. Text:存储长字符串。一般可以存储6W多个字符。如果超出了这个范围,可以使用LONGTEXT类型。映射到数据库中就是text类型。
  12. LONGTEXT:长文本类型,映射到数据库中是longtext类型。只能用于Mysql数据库。

Column常用参数

  1. primary_key:设置某个字段为主键。
  2. autoincrement:设置这个字段为自动增长的。
  3. default:设置某个字段的默认值。在发表时间这些字段上面经常用。
  4. nullable:指定某个字段是否为空。默认值是True,就是可以为空。
  5. unique:指定某个字段的值是否唯一。默认是False。
  6. onupdate:在数据更新的时候会调用这个参数指定的值或者函数。在第一次插入这条数据的时候,不会用onupdate的值,只会使用default的值。常用的就是update_time(每次更新数据的时候都要更新的值)。
  7. name:指定ORM模型中某个属性映射到表中的字段名。如果不指定,那么会使用这个属性的名字来作为字段名。如果指定了,就会使用指定的这个值作为参数。这个参数也可以当作位置参数,在第1个参数来指定。
  8. comment:在数据库中的注释。

Flask开启debug模式的几种方式:

  1. app.run(debug=True)中传递一个参数debug=True就可以开启DEBUG模式。
  2. 设置app.deubg=True,就可以开启debug模式。
  3. 通过配置参数的形式设置DEBUG模式:app.config.update(DEBUG=True)
  4. 通过配置文件的形式设置DEBUG模式:。
    新建一个config.py文件:

    #encoding: utf-8
    DEBUG=True

    导入

    import config
    app.config.from_object(config)

安装virtualenv

首先安装python的运行环境,安装完毕后,查看是否安装了pip,输入pip -V即可查看pip的版本。
然后我们可以使用pip install virtualenv安装virtualenv。
注意:

  • 如果你的pip的版本太低。可能会安装失败,我们可以使用python -m pip install --upgrade pip更新pip,如果报错的话,我们就输入命令:python -m pip install -U pip来更新。
  • 使用virtualenv --version可以查看你的pip的版本。

创建虚拟环境

我们可以通过virtualenv venv命令 创建名为 venv 的虚拟环境。
注意:

  • 如果创建失败显示failed to create process的错误,那么就卸载了virtualenv,卸载命名pip uninstall virtualenv,重新安装之前那,检查自己的环境变量是不是有问题,是不是有其他的python环境的变量。检查完成后,重新安装virtualenv即可。

    激活与退出

  • 激活命令:venv\Scripts\activate
  • 退出命令:deactivate

如果是在一个平面里面来计算两个点之间的距离,那么我们可以直接使用勾股定理,那么问题就来了,地球是一个球啊,面是球面啊,那就这么计算

from math import radians, cos, sin, asin, sqrt

#公式计算两点间距离(m)

def geodistance(lng1,lat1,lng2,lat2):
  lng1, lat1, lng2, lat2 = map(radians, [float(lng1), float(lat1), float(lng2), float(lat2)]) # 经纬度转换成弧度
  dlon=lng2-lng1
  dlat=lat2-lat1
  a=sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 
  distance=2*asin(sqrt(a))*6371*1000 # 地球平均半径,6371km
  distance=round(distance/1000,3)
  return distance

设计思路:

  • 产生一个0到1的随机数
  • 循环遍历需要产生概率的列表,以及对应的概率列表
  • 判断随机数是否比第一个数小,小的话就直接返回,并且结束循环,否则就进行下次循环,现在可以肯定比上一个数大,所以让第一个概率加上第二个概率再和产生的随机数进行比较。以此类推。
    函数实现:

    import random
    
    def random_pick(some_list,probabilitie_list):
      x=random.uniform(0, 1)
      cumulative_probability = 0.0
      for item,item_probability in zip(some_list,probabilitie_list):
          cumulative_probability = cumulative_probability + item_probability
          if x < cumulative_probability:
              break
      return item

    参数说明:

  • some_list:求概率的列表
  • probabilitie_list:概率列表

测试函数:

i=0
while i<100:
    i+=1
    print random_pick(['a','b','c','d'],[0.4,0.2,0.3,0.1])

python这门语言真的是很简洁,同时我们要提高我们的编程效率可以使用一些简单的方式,比如我们今天所说的字典推导和集合推导。

集合推导

list1 = [1,2,3,4,5]
list2 = [x+1 for x in list1]

那么list2的值就是:
[2,3,4,5,6]

字典推导

字典推导也是一样的

dict = { x: x % 2 == 0 for x in range(1, 6) }

那么dict的值就是
{1: False, 2: True, 3: False, 4: True, 5: False}

首先需要导入re模块import re

re库中常用方法

  • re.search(pattern, string, flags=0)遍历整个字符串并返回第一个成功的匹配。
  • re.match(pattern, string, flags=0)尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

    pattern :匹配的正则表达式
    string :要匹配的字符串。
    flags :标志位,用于控制正则表达式的匹配方式
  • re.sub(pattern, repl, string, count=0)用于替换字符串中的匹配项,repl : 替换的字符串,也可为一个函数。

    pattern : 正则中的模式字符串。
    repl : 替换的字符串,也可为一个函数。
    string : 要被查找替换的原始字符串。
    count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
  • re.compile(pattern[, flags])用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

    pattern : 一个字符串形式的正则表达式
    flags : 标志位,用于控制正则表达式的匹配方式
  • findall(string[, pos[, endpos]])在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

    string : 待匹配的字符串。
    pos : 可选参数,指定字符串的起始位置,默认为 0。
    endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
  • re.split(pattern, string[, maxsplit=0, flags=0])能够匹配的子串将字符串分割后返回列表。

    pattern: 匹配的正则表达式
    string: 要匹配的字符串。
    maxsplit: 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
    flags: 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

常用的匹配规则总结表

  • \w匹配字母数字及下划线
  • \W匹配非字母数字及下划线
  • \s匹配任意空白字符,等价于 [\t\n\r\f].
  • \S匹配任意非空字符
  • \d匹配十进制数字,等价于 [0-9]
  • \D匹配任意非数字
  • \A匹配字符串开始
  • \Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
  • \z匹配字符串结束
  • \G匹配最后匹配完成的位置
  • \n匹配一个换行符
  • \t匹配一个制表符
  • .除换行外任意一个字符
  • ^匹配字符串的开头
  • $匹配字符串的末尾
  • .匹配任意字符,除了换行符
  • [...]用来表示一组字符,单独列出:[amk] 匹配 'a','m' 或 'k'
  • [^...]不在 [] 中的字符:[^abc]匹配除了 a,b,c 之外的字符。
  • *匹配 0 个或多个的表达式。
  • +匹配 1 个或多个的表达式。
  • ?匹配 0 个或 1 个由前面的正则表达式定义的片段,非贪婪方式
  • {n}精确匹配 n 个前面表达式。
  • {n,} 至少n次
  • {n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
  • a | b匹配 a 或 b
  • ( )匹配括号内的表达式,也表示一个组

修饰符总结

  • re.I使匹配对大小写不敏感
  • re.L做本地化识别(locale-aware)匹配
  • re.M多行匹配,影响 ^$
  • re.S使 . 匹配包括换行在内的所有字符
  • re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B
  • re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。
"p.*y"#贪婪模式
"p.*?y"#懒惰模式,精准

D1r.jpg

python中常见的文件的操作,对于文件的操作常用的就是读取以及写入了,在这里小编介绍几种常用的操作方法。

Python字符串可以是二进制数据,而不是仅仅是文字。

open 函数

open()函数的作用是打开一个文件,并且创建一个file对象。
语法file object = open(file_name [, access_mode][, buffering])
参数

  • file_name:file_name指的是你要操作的文件的路径以及文件名。
  • access_mode:access_mode指的是打开文件的模式:只读,写入,追加等模式。
  • buffering:buffering指的是寄存的大小,如果buffering等于0,就不会有寄存。如果buffering等于1,访问文件时会寄存行。如果将buffering大于1的整数,表明了这就是的寄存区的缓冲大小。如果buffering小于0,寄存区的缓冲大小则为系统默认。

access_mode的取值:

  • r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
  • rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
  • r+打开一个文件用于读写。文件指针将会放在文件的开头。
  • rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
  • w打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • wb以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • w+打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • wb+以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
  • a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
  • ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
  • a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
  • ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

file对象的属性

  • file.name返回文件的名称。
  • file.mode返回被打开文件的访问模式。
  • file.closed文件已被关闭则返回true,否则返回false。
  • file.softspace末尾是否强制加空格。

close()函数

file对象的 close()方法刷新缓冲区里任何还没写入的信息,并关闭该文件,这之后便不能再进行写入。当一个文件对象的引用被重新指定给另一个文件时,Python 会关闭之前的文件。
语法:语法:fileObject.close();

write()函数

write()方法可将任何字符串写入一个已经打开的文件。并且write()方法不会在字符串的结尾添加换行符('\n')。并且write()之后一定要close().
语法fileObject.write(String);
参数:String是要写入到已打开文件的内容。

read()函数

read()方法从一个打开的文件中读取一个字符串。
语法fileObject.read([count]);
参数:count参数是要从已打开文件中读取的字节的个数。该方法从文件的开头开始读入,如果没有传入count,它会尝试尽可能多地读取内容,很可能是直到文件的末尾。

readline()函数

fileObject.readline() 会从文件中读取单独的一行。换行符为 '\n'。当读取到最后一行时,则返回一个空字符串。
语法fileObject.readline()

readlines()函数

fileObject.readlines()将以列表的形式返回该文件中包含的所有行,列表中的一项表示文件的一行
语法fileObject.readlines([sizehint])
参数:sizehint, 则读取指定长度的字节, 并且将这些字节按行分割。

rename()函数

rename()对文件重命名。
语法fileObject.rename(current_file_name, new_file_name)

remove()函数

删除文件。
语法fileObject.remove(file_name)

mkdir()函数

mkdir()方法在当前目录下创建新的目录们。
语法fileObject.mkdir(new_dir)

chdir()函数

可以用chdir()方法来改变当前的目录。
语法fileObject.chdir(new_dir)
参数:newdir是你想设成当前目录的目录名称。

getcwd()函数

getcwd()方法显示当前的工作目录。
语法fileObject.getcwd()

rmdir()函数

rmdir()方法删除目录,目录名称以参数传递。在删除这个目录之前,它的所有内容应该先被清除。
语法fileObject.rmdir(dir_name)
pink_eyes-shirt-1140x600.jpg

python获取本周(上周)本月(上月)开始时间以及结束时间

导包

import time
import datetime

获取当前日期

today = datetime.date.today()

本周的开始以及结束日期

# 开始日期
today - datetime.timedelta(days=today.weekday()+7)
# 结束日期
today - datetime.timedelta(days=today.weekday()+1)

上周的开始日期以及结束日期

# 获取当前日期 
date = datetime.datetime.now()
# 上周开始时间
date-datetime.timedelta(days=date.weekday()+7)
# 上周结束时间
date-datetime.timedelta(days=date.weekday()+1)

本月开始以及结束日期

# 获取当前日期 
date = datetime.datetime.now()
year = date.year
month = date.month
# 开始日期
start = datetime.date(year, month, 1)
#结束日期
if month == 12:
    end = datetime.date(year+1, 1, 1) - datetime.timedelta(days=1)
else:
    end = datetime.date(year, month+1, 1) - datetime.timedelta(days=1)

上个月的开始以及结束日期

# 获取当前日期 
date = datetime.datetime.now()
year = date.year
month = date.month
if month == 1:
    start = datetime.date(year-1, 12, 1)
else:
    start = datetime.date(year, month-1, 1)
end = datetime.date(year, month, 1) - datetime.timedelta(days=1)