datetime模块,单线程,多线程


datetime

from datetime import datetime
?
dq = datetime.now()   # 当前时间
print(dq)
print(dq.date()) # 日期
print(dq.time()) # 时间
C:\Users\栀寒老酒\AppData\Local\Programs\Python\Python39\python.exe C:/Users/栀寒老酒/PycharmProjects/pythonProject/main.py
2022-03-10 20:40:21.027839
2022-03-10
20:40:21.027839
进程已结束,退出代码0
?
?
import time
print(time.time())
还有
ret = dq.timestamp()  
print(ret)
:
1646916621.478163
# 1970,1.1.0.0 到现在 一共有多少毫秒
?
MDN WEB DOCS--->
   
JavaScript Date objects represent a single moment in time in a platform-independent format. Date objects contain a Number that represents milliseconds since 1 January 1970 UTC.
?
?
?
#时间戳就是1970,1.1.0.0 到现在 一共有多少毫秒
ret = dq.timestamp()   转成时间戳
print(ret)   #1970,01.01.00:00 到现在 一共有多少毫秒
1646916621.478163
ret1 = datetime.fromtimestamp(ret)    # 通过时间戳算出时间
print(ret1)
:
2022-03-10 20:50:21.478163
?
#timetuple
from datetime import datetime
print(datetime.now().timetuple())
:
time.struct_time(tm_year=2022, tm_mon=3, tm_mday=10, tm_hour=20, tm_min=46, tm_sec=40, tm_wday=3, tm_yday=69, tm_isdst=-1)
#本来今天是星期四,但这里是星期三,因为国外一周是0-6,国内是1-7
#tm_isdst=-1是夏令时
# 格式化输出
print(ret1.strftime('%Y{y}%m{m}%d{d}').format(y='年',m='月',d='日'))    
2022年03月10日
?
# 时间计算timedelta
import datetime   #这个datetime不是from datetime import datetime里的datetime
ret = datetime.datetime.now()  # 当前时间
td = datetime.timedelta(hours=8,minutes=11,seconds=38)
print(ret - td)
print(ret + td)
2022-03-10 12:44:38.529254
2022-03-11 05:07:54.529254
# 两个日期时间对象的差值就是对象
?
import datetime
?
s1 = datetime.datetime.now()
?
# 获取一个时间对象,然后转换成时间戳
s2 = datetime.datetime.now().timestamp()  
1647078429.422437
?
# 时间戳转换日期时间
s3 = datetime.datetime.fromtimestamp(s2)  
2022-03-12 17:47:09.422437
?
#%H:%M:%S
s4 = datetime.datetime.now().strftime('%y-%m-%d')  #只能用-
print(s4)
22-03-10
?
# 前面是什么格式 后面就一定要跟什么样的格式
s5 = datetime.datetime.strptime(s4,'%y-%m-%d')  
print(s5)
2022-03-10 00:00:00
       
#转换时间和日期
import datetime
qqq = datetime.time(20,59,9)
print(qqq)
20:59:09
       
www = datetime.date(2002,1,5)    #不能写01,05,不能有0
print(www)
2002-01-05

线程概念

线程
进程是cpu资源分配的最小单位,线程是cpu调度的最小单位。
?
并发--时间片:同时可以跑多少个线程,每个线程你执行一下,我执行一下,来回切换,只要切换够快,你就发现不了其实一个时间内只执行一个线程
?
并行--多进程
几核就是最多能进行几个进程
?
一个进程里面最少有一个线程

多线程

#单线程,挨住处理,从上向下执行,处理完前面的才能处理下面的
def sing():
   for i in range(4):
       print('sing...')
?
def dance():
   for i in range(4):
       print('dance...')
?
if __name__ == '__main__':
   sing()
   dance()
:
sing...
sing...
sing...
sing...
dance...
dance...
dance...
dance...
   
?
#多线程(并发)
import threading,time
def sing():
   print('sing...')
   time.sleep(3)
   print('唱歌结束')
?
def dance():
   print('dance...')
   time.sleep(3)
   print('跳舞结束')
?
if __name__ == '__main__':
   f_sing = threading.Thread(target=sing,name='hello')
   f_dance = threading.Thread(target=dance)#不给名字的话系统会默认有一个名字
   # 将子线程设为守护线程,创建出来两个子线程
   
   f_sing.start() #启动子线程
   f_dance.start()
?
   print('主线程执行完毕')
以上输出的效果是:
sing...
dance...
主线程执行完毕
#过三秒    
唱歌结束
跳舞结束
#也就是说,if __name__ == '__main__':里执行的时候,不管sing和dance执没执行完,都会继续往下执行,比如f_sing给张三,f_dance给李四,不管他俩有没有干完,轮到它它会开始执行,但是不会等它执行完毕,会立马执行主线程下面的程序,不会等待子线程执行完毕
?
主线程不是一个任务,是一个顺序
#如果之后还有函数比如func()想用子线程的结果,但是由于它会直接往下执行,导致用不到,一般来说,我们是希望主线程等子线程执行完毕之后再往下走,所以引入了阻塞的概念
if __name__ == '__main__':
   f_sing = threading.Thread(target=sing,name='hello')
   f_dance = threading.Thread(target=dance)#不给名字的话系统会默认有一个名字
   # 将子线程设为守护线程,创建出来两个子线程  
   
   f_sing.start() #启动子线程
   f_dance.start()
   
   f_sing.join() #阻塞
   f_dance.join()
   
   print('主线程执行完毕')
def func():
  ......
#效果是:
sing...
dance...
#过三秒:
跳舞结束
唱歌结束
主线程执行完毕   #子线程执行完毕才接着往下执行
?
?
但是又产生了一个问题,万一主线程因为特殊的原因结束了,而子线程还挂在那里,时间性能都浪费了,出来的结果对我们也没有用,所以还给他加一个守护线程,守护线程的作用是,只要主线程结束或者执行完毕,不管子线程是否执行完毕,都会强制结束
if __name__ == '__main__':
  f_sing = threading.Thread(target=sing,name='hello')
  f_dance = threading.Thread(target=dance)#不给名字的话系统会默认有一个名字
  #创建出来两个子线程  
 
  f_sing.setDaemon(True)   #将子线程设为守护线程
  f_dance.setDaemon(True)  #里面是True就是开启守护,里面是布尔值
 
  f_sing.start() #启动子线程
  f_dance.start()
   
  f_sing.join() #阻塞
  f_dance.join()
   
   print('主线程执行完毕')
def func():  
#效果是:
sing...
dance...
主线程执行完毕
进程已结束,退出代码0
?
##最完整:
import threading,time
def sing():
   print('sing...')
   time.sleep(3)
   print('唱歌结束')
def dance():
   print('dance...')
   time.sleep(3)
   print('跳舞结束')
if __name__ == '__main__':
   f_sing = threading.Thread(target=sing, name='hello')
   f_dance = threading.Thread(target=dance)  
   
   f_sing.setDaemon(True)  
   f_dance.setDaemon(True)  
   
   f_sing.start()
   f_dance.start()
?
   f_sing.join()  
   f_dance.join()
?
   print('主线程执行完毕')
#任务多的话就引入线程池的概念
?
#名字
if __name__ == '__main__':
   f_sing = threading.Thread(target=sing, name='hello')
   f_dance = threading.Thread(target=dance)
   
   print(f_sing.getName())   #打印名字
   f_sing.getName("new_name")  #修改名字
   
   
#run方法,start方法继承的run方法,只要用到start方法,他就会去找我们的run方法
import time
from threading import Thread
?
class Myqy(Thread):
   def run(self):
       print('hello')
       time.sleep(3)
       print('bye')
?
qy_ie = Myqy()
qy_ie.start() # 底层调用的是run方法
#效果:
hello
#过三秒
bye
#虽然用的是start方法,但执行的是run方法
#start是专门启动子线程的方法,而run只是普通的调用了一个函数
?
#复习:
"""
完全继承   不需要新的参数   不要init
不继承                   需要
要继承   要新参数         init   super
"""

#####这是无锁#####
from threading import Thread
a = 0
def f():
   global a
   for i in range(1000000):
       a += 1    
def f1():
   global a
   for i in range(1000000):
       a -= 1              
if __name__ == '__main__':
?
   print(a)
?
   t = Thread(target=f)
   t1 = Thread(target=f1)
   t.start()
   t1.start()
   t.join()
   t1.join()
?
   print(a)
:
0          0         0         ...
203998     344245    -299276   ...
#每次运行出来的结果都不相同,原因就是出现了资源互抢,如果是多核(多进程)就不会有资源抢夺,加装cpu就可以,但是很贵
# a = a + 1===>它是分两步的:2步   1.先获取到值   2 进行赋值
                                 #a=0           0 +1 = 1
#但获取值以后在进行赋值的时候可能被f1抢走了,同理a-=1也是,而次数都正常的消耗了一次,所以造成了资源抢夺,次数越多差值越大,解决办法就是上锁
from threading import Thread,Lock
?
lock = Lock()
?
a = 0
def f():
   global a
   lock.acquire()
   for i in range(1000000):
       a += 1    
       
   lock.release()
?
def f1():
   global a
   lock.acquire()
   for i in range(1000000):
       a -= 1            
   lock.release()          ###上锁以后要解开
?
if __name__ == '__main__':
?
   print(a)
?
   t = Thread(target=f)
   t1 = Thread(target=f1)
   t.start()
   t1.start()
   t.join()
   t1.join()
?
   print(a)
:
0
0
#这次就正常了
?
死锁  两个线程分别占有对方的一部分资源并且同时等待对方的资源就会造成死锁,两个线程都在等数据过来,但它们有锁,数据拿不到,就会在那一直等下去,也就是死锁,解决办法就是队列,这个下一个文章会说
?
拓展:C语言特有的一把锁,GIL 全局解释器锁   单核的情况下可以实现多任务(并发)
python的代码执行由python虚拟机(也叫解释器主循环,CPython版本)来控制,python在设计之初就考虑到在解释器的主循环中,同时只有一个线程在运行。即在任意时刻只有一个线程在解释器中运行。对python虚拟机访问的控制由全局解释锁GIL控制,正是这个锁来控制同一时刻只有一个线程能够运行。