常用模块学习(二)

  • 常用模块学习—包及跨模块导入

    • 当你的模块文件越来越多,就需要对模块文件进行划分,比如把负责跟数据库交互的都放一个文件夹,把与页面交互相关的放一个文件夹
      .
      └── my_proj
          ├── crm #代码目录
          │   ├── admin.py
          │   ├── apps.py
          │   ├── models.py
          │   ├── tests.py
          │   └── views.py
          ├── manage.py
          └── my_proj #配置文件目录
              ├── settings.py
              ├── urls.py
              └── wsgi.py

      一个文件夹管理多个模块文件,这个文件夹就被称为包

    • 那不同包之间的模块怎样互相导入呢?
      crm/views.py内容:
      def sayhi():
          print('hello world!')
      
      通过manage.py调用:
      from crm import views
      
      views.sayhi()

      用 python2 执行 manage.py:
      
      Alexs-MacBook-Pro:my_proj alex$ ls
      crm        manage.py    my_proj
      Alexs-MacBook-Pro:my_proj alex$ python manage.py 
      Traceback (most recent call last):
        File "manage.py", line 6, in <module>
          from crm import views
      ImportError: No module named crm      找不到模块

      包就是文件夹,但该文件夹下必须存在 __init__.py 文件, 该文件的内容可以为空。__int__.py用于标识当前文件夹是一个包。

    • 在crm目录下创建一个空文件__int__.py ,再执行一次
      Alexs-MacBook-Pro:my_proj alex$ touch crm/__init__.py #创建一个空文件
      Alexs-MacBook-Pro:my_proj alex$ 
      Alexs-MacBook-Pro:my_proj alex$ ls crm/
      __init__.py    admin.py    models.py    views.py
      __pycache__    apps.py        tests.py    views.pyc
      Alexs-MacBook-Pro:my_proj alex$ python manage.py 
      hello world!
      
      注意:在python3里,即使目录下没__int__.py文件也能创建成功,应该是解释器优化所致,但是创建包的时候还是要记得加上这个文件。
    • 例:
    • settings.py:
      DATABASES= {
          'host':'localhost'
      }
      print('in proj/settings.py')
      
      
      views.py:
      from proj import settings
      
      def sayhi():
          print('hello world!')
      
      
      manage.py:
      from crm import views
      
      views.sayhi()
      
      执行 manage.py

  • 常用模块学习—跨模块导入2

     1 import sys,os
     2 
     3 #sys.path.append("E:/Python/work/myFirstPro/第4章/packages/my_proj/")
     4 #print(sys.path)
     5 #from proj import settings
     6 
     7 print(dir())                   #结果为:['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'os', 'sys']
     8 print(__file__)                #结果为:E:/Python/work/myFirstPro/第4章/packages/my_proj/crm/views.py
     9 
    10 #绝对路径
    11 DASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))       #abspath 绝对路径
    12 sys.path.append(DASE_DIR)
    13 from proj import settings
    14 
    15 #相对路径
    16 # DASE_DIR = os.path.dirname(os.path.dirname(__file__))        #os.path.dirname(__file__)   使目录往上走一层
    17 # print(DASE_DIR)                               #结果为:E:/Python/work/myFirstPro/第4章/packages/my_proj
    18 # sys.path.append(DASE_DIR)
    19 # from proj import settings                    #结果为:in proj/settings.py
    20 
    21 def sayhi():
    22     print('hello world!')
  • 常用模块学习—相对导入

    绝对导入&相对导入
    在linux里可以通过cd ..回到上一层目录 ,cd ../.. 往上回2层,这个..就是指相对路径,在python里,导入也可以通过..
    
    例如:
    .
    ├── __init__.py
    ├── crm
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   ├── views.py  #from ..proj import settings 
    ├── manage.py   
    └── proj
        ├── __init__.py
        ├── settings.py #from .import urls  
        ├── urls.py
        └── wsgi.py
    
    views.py里代码:
    from ..proj import settings
    def sayhi():
        print('hello world!')
    
    print(settings.DATABASES)
    
    执行结果报错了:
    Traceback (most recent call last):
    File "my_proj/crm/views.py", line 4, in <module>
     from ..proj import settings
    SystemError: Parent module '' not loaded, cannot perform relative import
    
    或者有人会看到这个错
    ValueError: attempted relative import beyond top-level package
    
    
    其实这两个错误的原因归根结底是一样的:在涉及到相对导入时,package所对应的文件夹必须正确的被python解释器视作package,而不是普通文件夹。否则由于不被视作package,无法利用package之间的嵌套关系实现python中包的相对导入。
    
    
    文件夹被python解释器视作package需要满足两个条件:
    1、文件夹中必须有__init__.py文件,该文件可以为空,但必须存在该文件。
    2、不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口)。
    
    
    解决办法就是,既然你在views.py里执行了相对导入,那就不要把views.py当作入口程序,可以通过上一级的manage.py调用views.py
    
    .
    ├── __init__.py
    ├── crm
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── models.py
    │   ├── tests.py
    │   ├── views.py  #from ..proj import settings 
    ├── manage.py  #from crm import views 
    └── proj
        ├── __init__.py
        ├── settings.py #from .import urls  
        ├── urls.py
        └── wsgi.py
    
    事实证明还是不行,报错:
    ValueError: attempted relative import beyond top-level package
    
    
    但把from ..proj import settings 改成from . import models 后却执行成功了,为什么呢?
    
    from .. import models会报错的原因是,这句代码会把manage.py所在的这一层视作package,但实际上它不是,因为package不能是顶层入口代码,若想不出错,只能把manage.py往上再移一层。
    
    正确的代码目录结构如下:
     packages/
        ├── __init__.py
        ├── manage.py #from my_proj.crm  import views
        └── my_proj
            ├── crm
            │   ├── admin.py
            │   ├── apps.py
            │   ├── models.py
            │   ├── tests.py
            │   ├── views.py  #from . import models;  from ..proj import settings 
            └── proj
                ├── __init__.py
                ├── settings.py
                ├── urls.py
                └── wsgi.py
    
    再执行manage.py就不会报错了。
    
    注意:虽然python支持相对导入,但对模块间的路径关系要求比较严格,处理不当就容易出错,so并不建议在项目里经常使用。
  • 常用模块学习—time 模块详解

在平常的代码中,我们常常需要与时间打交道。在Python中,与时间处理有关的模块就包括:time,datetime,calendar

    • 在Python中,通常有这几种方式来表示时间:
      • 时间戳
      • 格式化的时间字符串
      • 元组(struct_time)共九个元素。由于Python的time模块实现主要调用C库,所以各个平台可能有所不同。
    • 几个定义
      • UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。
      • 时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。
      • 元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有gmtime(),localtime(),strptime()。下面列出这种方式元组中的几个元素:
        索引(Index)    属性(Attribute)    值(Values)
        0     tm_year(年)                 比如2011 
        1     tm_mon(月)                  1 - 12
        2     tm_mday(日)                 1 - 31
        3     tm_hour(时)                 0 - 23
        4     tm_min(分)                  0 - 59
        5     tm_sec(秒)                  0 - 61
        6     tm_wday(weekday)            0 - 6(0表示周日)
        7     tm_yday(一年中的第几天)       1 - 366
        8     tm_isdst(是否是夏令时)            默认为-1
    • time模块的方法

      • time.localtime([secs]):将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。
      • time.gmtime([secs]):和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
      • time.time():返回当前时间的时间戳。
      • time.mktime(t):将一个struct_time转化为时间戳。
      • time.sleep(secs):线程推迟指定的时间运行。单位为秒。
      • time.asctime([t]):把一个表示时间的元组或者struct_time表示为这种形式:'Sun Oct 1 12:04:38 2017'。如果没有参数,将会将time.localtime()作为参数传入。
      • time.ctime([secs]):把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。
      • time.strftime(format[, t]):把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。

        • 举例:time.strftime("%Y-%m-%d %X", time.localtime()) #输出'2017-10-01 12:14:23'
      • time.strptime(string[, format]):把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。

        • 举例:time.strptime('2017-10-3 17:54',"%Y-%m-%d %H:%M") #输出 time.struct_time(tm_year=2017, tm_mon=10, tm_mday=3, tm_hour=17, tm_min=54, tm_sec=0, tm_wday=1, tm_yday=276, tm_isdst=-1)

 

    • 字符串转时间格式对应表

       1 %a            Locale’s abbreviated weekday name.    
       2 %A            Locale’s full weekday name.    
       3 %b            Locale’s abbreviated month name.    
       4 %B            Locale’s full month name.    
       5 %c            Locale’s appropriate date and time representation.    
       6 %d            Day of the month as a decimal number [01,31].    
       7 %H            Hour (24-hour clock) as a decimal number [00,23].    
       8 %I            Hour (12-hour clock) as a decimal number [01,12].    
       9 %j            Day of the year as a decimal number [001,366].    
      10 %m            Month as a decimal number [01,12].    
      11 %M            Minute as a decimal number [00,59].    
      12 %p            Locale’s equivalent of either AM or PM.    (1)
      13 %S            Second as a decimal number [00,61].    (2)
      14 %U            Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.    (3)
      15 %w            Weekday as a decimal number [0(Sunday),6].    
      16 %W            Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0.    (3)
      17 %x            Locale’s appropriate date representation.    
      18 %X            Locale’s appropriate time representation.    
      19 %y            Year without century as a decimal number [00,99].    
      20 %Y            Year with century as a decimal number.    
      21 %z            Time zone offset indicating a positive or negative time difference from UTC/GMT of the form +HHMM or -HHMM, where H represents decimal hour digits and M represents decimal minute digits [-23:59, +23:59].    
      22 %Z            Time zone name (no characters if no time zone exists).    
      23      %%    A literal '%' character.

 

 

import time

#返回当前时间的时间戳
time.time()
#结果为:1537339625.2724273
time.time()
#结果为:1537339629.5167184
time.time()
#结果为:1537339633.3674865
time.time()
#结果为:1537339650.316459
time.time()
#结果为:1537339651.5483134
time.time()
#结果为:1537339652.9071617
time.time()
#结果为:1537339654.12688
time.time() / 3600 /24 /365
#结果为:48.74872318235897


#将一个时间戳转换为当前时区的struct_time
time.localtime()
#结果为:time.struct_time(tm_year=2018, tm_mon=9, tm_mday=19, tm_hour=14, tm_min=50, tm_sec=32, tm_wday=2, tm_yday=262, tm_isdst=0)
time.localtime()
#结果为:time.struct_time(tm_year=2018, tm_mon=9, tm_mday=19, tm_hour=14, tm_min=50, tm_sec=39, tm_wday=2, tm_yday=262, tm_isdst=0)
a = time.localtime()
a.tm_year
#结果为:2018
'%s-%s-%s'%(a.tm_year,a.tm_mon,a.tm_mday)
#结果为:'2018-9-19'


#和localtime()方法类似,将一个时间戳转换为UTC时区(0时区)的struct_time
time.gmtime()
#结果为:time.struct_time(tm_year=2018, tm_mon=9, tm_mday=19, tm_hour=7, tm_min=6, tm_sec=12, tm_wday=2, tm_yday=262, tm_isdst=0)
a=time.localtime(1403232424)
a
#结果为:time.struct_time(tm_year=2014, tm_mon=6, tm_mday=20, tm_hour=10, tm_min=47, tm_sec=4, tm_wday=4, tm_yday=171, tm_isdst=0)
a=time.localtime(140323242)
a
#结果为:time.struct_time(tm_year=1974, tm_mon=6, tm_mday=13, tm_hour=10, tm_min=40, tm_sec=42, tm_wday=3, tm_yday=164, tm_isdst=0)


#将一个struct_time转化为时间戳
time.mktime(a)
#结果为:140323242.0


#线程推迟指定的时间运行。单位为秒
time.sleep(2)


#把一个表示时间的元组或者struct_time表示为这种形式:'Sun Oct 1 12:04:38 2017'。如果没有参数,将会将time.localtime()作为参数传入。
time.asctime()
#结果为:'Wed Sep 19 18:12:52 2018'


#把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式
time.ctime()
#结果为:'Wed Sep 19 18:13:21 2018'
time.ctime(123232)
#结果为:'Fri Jan  2 18:13:52 1970'
time.ctime(0)
#结果为:'Thu Jan  1 08:00:00 1970'


#把一个代表时间的元组或者struct_time 转化为格式化的时间字符串。
time.strftime('%Y-%m-%d')
#结果为'2018-09-19'
time.strftime('%Y-%m-%d %H:%M:%S',)
#结果为'2018-09-19 18:19:16'
time.strftime('%Y-%m-%d %H:%M:%S',a)
#结果为'1974-06-13 13:40:42'
time.strftime('%Y-%m-%d %H:%M:%S %a',a)
#结果为'1974-06-13 13:40:42 Thu'
time.strftime('%Y-%m-%d %H:%M:%S %A',a)
#结果为'1974-06-13 13:40:42 Thursday'
time.strftime('%Y-%m-%d %H:%M:%S %p',a)
#结果为'1974-06-13 13:40:42 AM'
time.strftime('%Y-%m-%d %H:%M:%S %U')
#结果为'2018-09-19 18:20:36 37'
time.strftime('%Y-%m-%d %H:%M:%S %w')
#结果为'2018-09-19 18:21:02 3'
time.strftime('%y-%m-%d %H:%M:%S %w')
#结果为'18-09-19 18:21:29 3'
time.strftime('%y-%m-%d %H:%M:%S %z')
#结果为'18-09-19 18:21:41 +0800'
time.strftime('%y-%m-%d %H:%M:%S %Z')
#结果为'18-09-19 18:21:45 ?D1¨²¡À¨º¡Á?¨º¡À??'


#把一个格式化时间字符串转化为struct_time,实际上它和strftime()是逆操作。
s=time.strftime('%Y %m-%d %H:%M:%S')
s
#结果为'2018 09-19 18:26:23'
time.strptime(s,'%Y %m-%d %H:%M:%S')
#结果为time.struct_time(tm_year=2018, tm_mon=9, tm_mday=19, tm_hour=18, tm_min=26, tm_sec=23, tm_wday=2, tm_yday=262, tm_isdst=-1)
s2 = time.strptime(s,'%Y %m-%d %H:%M:%S')
time.mktime(s2)
#结果为1537341983.0

 

  • 常用模块学习—tatetime 模块详解

 

相比于time模块,datetime模块的接口则更直观、更容易调用。

datetime模块定义了下面这几个类:

  • datetime.date:表示日期的类。常用的属性有year, month, day;
  • datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond;
  • datetime.datetime:表示日期时间。
  • datetime.timedelta:表示时间间隔,即两个时间点之间的长度。
  • datetime.tzinfo:与时区有关的相关信息。(这里不详细充分讨论该类,感兴趣的童鞋可以参考python手册)

 

我们需要记住的方法仅以下几个:

  •  d=datetime.datetime.now() 返回当前的datetime日期类型
     d.timestamp(),d.today(), d.year,d.timetuple()等方法可以调用
  • datetime.date.fromtimestamp(322222) 把一个时间戳转为datetime日期类型

 

  • 时间运算
>>> datetime.datetime.now()

datetime.datetime(2017, 10, 1, 12, 53, 11, 821218)

>>> datetime.datetime.now() + datetime.timedelta(4) #当前时间 +4天

datetime.datetime(2017, 10, 5, 12, 53, 35, 276589)

>>> datetime.datetime.now() + datetime.timedelta(hours=4) #当前时间+4小时

datetime.datetime(2017, 10, 1, 16, 53, 42, 876275)
  • 时间替换
>>> d.replace(year=2999,month=11,day=30)

datetime.date(2999, 11, 30)

 

import datetime
import time
datetime.datetime.now()
#结果为:datetime.datetime(2018, 9, 19, 19, 9, 38, 72617)
a=datetime.datetime.now()
a.year
#结果为:2018
a.month
#结果为:9
a
#结果为:datetime.datetime(2018, 9, 19, 19, 10, 30, 236846)
time.time()
#结果为:1537344708.7243214
datetime.date.fromtimestamp(time.time())
#结果为:datetime.date(2018, 9, 19)
d2 = datetime.date.fromtimestamp(time.time())
d2.year
#结果为:2018
d2.timetuple()
#结果为:time.struct_time(tm_year=2018, tm_mon=9, tm_mday=19, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=262, tm_isdst=-1)


#时间运算
datetime.timedelta(1)
#结果为:datetime.timedelta(days=1)
datetime.datetime.now()
#结果为:datetime.datetime(2018, 9, 19, 19, 18, 18, 334682)
t = datetime.timedelta(1)
datetime.datetime.now() - t
#结果为:datetime.datetime(2018, 9, 18, 19, 18, 33, 472953)
datetime.datetime.now() - datetime.timedelta(days=1)
#结果为:datetime.datetime(2018, 9, 18, 19, 19, 45, 149420)
datetime.datetime.now() - datetime.timedelta(days=4)
#结果为:datetime.datetime(2018, 9, 15, 19, 19, 57, 147533)
datetime.datetime.now() - datetime.timedelta(hours=3)
#结果为:datetime.datetime(2018, 9, 19, 16, 20, 17, 150411)
datetime.datetime.now() + datetime.timedelta(hours=3)
#结果为:datetime.datetime(2018, 9, 19, 22, 20, 29, 46632)
datetime.datetime.now() + datetime.timedelta(minutes=3)
#结果为:datetime.datetime(2018, 9, 19, 19, 23, 43, 578674)
datetime.datetime.now() + datetime.timedelta(seconds=3)
#结果为:datetime.datetime(2018, 9, 19, 19, 21, 14, 1416)


#时间替换
datetime.datetime.now()
#结果为:datetime.datetime(2018, 9, 19, 19, 24, 16, 789861)
d = datetime.datetime.now()
d.replace()
#结果为:datetime.datetime(2018, 9, 19, 19, 24, 22, 384904)
d.replace(year=2016)
#结果为:datetime.datetime(2016, 9, 19, 19, 24, 22, 384904)
d.replace(year=2016,month=8)
#结果为:datetime.datetime(2016, 8, 19, 19, 24, 22, 384904)
d.replace(year=2016,month=8,day=21)
#结果为:datetime.datetime(2016, 8, 21, 19, 24, 22, 384904)