Python瞎记

在这里记一下使用Python过程中比较鸡肋的操作,就是很基础但又容易忘记还不好谷歌的那种操作。


Python模块

重新载入模块

在Python2.X中,可以通过内置函数reload重新载入模块。reload可以在模块被修改的情况下不必关闭Python而重新载入模块。在使用reload重载入模块时,该模块必须事先已经被导入。
在Python3.X中,reload函数已经被删除,要重新再入模块,则必须使用imp模块中的reload函数(如:imp.reload(os) #重新载入os模块)。

Python在哪里查找模块

编写好的模块只有被Python找到才能被导入。

在导入模块时,Python解释器首先在当前目录中查找要导入的模块。如果未找到模块,则Python解释器会从sys模块中path变量指定的目录中查找导入模块。如果在以上所有目录中都未找到导入的模块,则会输出出错信息。

在脚本中可以向sys.path添加模块查找路径:
例如:

import os
import sys
modulepath=os.getcwd()+'\\module'		#将当前目录下的module子目录添加到sys.path中
sys.path.append(modulepath)
print(sys.path)
import mymodule							#从moudle目录中导入mymoudle模块

是否需要编译模块

当调用或运行完一个模块后,当前目录下会生成一个编译成的字节码文件(.pyc)。

虽然Python是脚本语言,但Python可以将脚本语言编译成字节码的形式。对于模块,Python总是在第一次调用后就将其编译成字节码文件,以提高脚本的启动速度。

对于非模块的脚本,Python不会在运行脚本后将其编译成字节码的形式。如果想将其编译,可以使用py_compile模块:
例如:

#file:bianyi.py
#
import py_compile		#导入py_compile模块
py_compile.compile('usemodule.py','usemodule.pyc')	#编译 usemodule.py

注意:在Python3中,如果在py_compile.compile函数中不指定第2个参数,则在当前目录新建一个名为“pycache”的目录,并在这个目录中生成“被编译模块名.cpython-32.pyc”的pytc字节码文件。

脚本优化编译

可以通过Python的命令行选项将脚本优化编译。Python编译的优化选项有两个:

-O 该选项对脚本的优化不多,编译后的脚本以“.pyo”为扩展名。凡是以“.pyo”为扩展名的Python字节码都是经过优化的。
-OO 该选项对脚本的优化的程度很大。使用该标志可以使编译的Python脚本更小。使用该选项可以导致脚本运行错误,因此,谨慎使用。

例如:

>>>python -O compile.py
>>>python -OO compile.py

如何查看模块提供的函数名

使用内置函数dir()来查看

dir([object])		#object 可选参数,要列举的模块名

例如:

	>>>import os
	>>>dir(os)		#获得os模块中的名字和函数
或者:
	>>>dir()		#获得当前脚本中所有名字列表

Psyco让 Python 运行得像 C 一样快

用 Psyco 让 Python 运行得像 C 一样快。
这玩意儿没用过,只是听说过,以后用到了再学习补充。

参考文章:
https://www.ibm.com/developerworks/cn/linux/sdk/python/charm-28/


得到列表中唯一元素值的最快方法set([1,1])

a = [1,2,3,3,4,5,5,5,5,6]
b = set(a)
b

Python线程

线程概念

几个概念:

  • 线程 — 是程序的执行分支,是程序中真正负责执行业务的地方。
  • 多线程 — 类似于同时执行多个不同的程序。
  • 并发 — 四百米接力赛
  • 并行 — 跑马拉松

优点:

  1. 可以把那些长时间处于等待的线程,放到后台去处理。 下载内容。等待文件。等待网络请求。等待数据库
  2. 给前端增加一些额外的特效。如:下载进度、触发事件(手机上点击某个应用的图标)。
  3. 让程序的执行速度更快。如:多线程下载(相当于空间换时间)

线程是包含于进程的。每个线程都有自己的CPU寄存器。称之为线程的上下文,用于反应线程上次运行的状态

Pyhon中的两种线程

Python中包含两种线程:

  1. 内核线程 — 由操作系统内核创建和撤销的。
  2. 用户线程 — 由用户创建和撤销的。

Python3中的两个线程模块

  1. threading(推荐使用)
  2. _thread

在低版本是有thread模块的,但在python3被废弃了,使用_thread来代替。

threading提供了几个函数:

thrading.currentThread()  #获取当前线程变量

thrading.enumerate()      #获取包含当前正在运行的线程的集合(list[]格式)

thrading.activeCount()    #获取当前存活的线程数量,和len(thrading.enumerate())一样。

Thread类还提供如下函数:

run()		# 线程活动的方法

start() 	#启动线程

join() 		#等待至线程中止。 A和B Bjoin A   让A等待。

isAlive()	#判断线程是否存活

getName()	 #获取线程名称

Python中创建线程的两种方法

  1. 用类来包装线程对象(推荐使用)
  2. 用函数

_thread 提供了低级别的原始的以及简单的锁,不完全,因此它的功能相比threading有限。

1、用类包装线程对象创建线程(推荐使用)

例如:

import threading
import time

# 设置一个标志。
exitFlag = 0
# 创建一个数据类型。名字叫做myThread. 该类型继承threading模块中的Thread类。
class myThread(threading.Thread):
    # 构造方法  用于构造myThread对象。 myThread类型的值。类似于i = 0
    def __init__(self, threadID, name, counter):
        # 调用父类的构造
        threading.Thread.__init__(self)
        # 完成参数赋值
        self.name = name
        self.threadID = threadID
        self.counter = counter

    # 重写的方法。线程实际执行的业务都必须放在这。
    def run(self):
        print("开始线程:{}".format(self.name))
        print_curr_time(self.name, self.counter, 5)
        print("结束线程:{}".format(self.name))


def print_curr_time(name, delay,counter):
    """
    用于打印当前时间
    :param name:   线程的名称
    :param delay:  延迟的时间
    :return:
    """
    while counter:
        # 让当前休眠。休眠delay的时间
        if exitFlag:
            name.exit()

        time.sleep(delay)
        print("{}\t{}".format(name, time.ctime(time.time())))
        counter -= 1


# 创建新线程
thread1 = myThread(1,"一只王八",1)
thread2 = myThread(2,"岂不美哉",2)


# 启动线程
thread1.start()
thread2.start()

thread1.join()
thread2.join()


print("退出主线程")

执行结果:

开始线程:一只王八
开始线程:岂不美哉
一只王八	Fri Dec 28 17:50:06 2018
岂不美哉	Fri Dec 28 17:50:07 2018
一只王八	Fri Dec 28 17:50:07 2018
一只王八	Fri Dec 28 17:50:08 2018
岂不美哉	Fri Dec 28 17:50:09 2018
一只王八	Fri Dec 28 17:50:09 2018
一只王八	Fri Dec 28 17:50:10 2018
结束线程:一只王八
岂不美哉	Fri Dec 28 17:50:11 2018
岂不美哉	Fri Dec 28 17:50:13 2018
岂不美哉	Fri Dec 28 17:50:15 2018
结束线程:岂不美哉
退出主线程

线程锁的用法

上面执行结果顺序有点“乱”,想要让线程按规定顺序执行的话就需要用到“锁”了。

这里的“锁”并不是指给资源加锁,而是用锁去锁定资源,你可以定义多个锁, 当你需要独占某一资源时,任何一个锁都可以锁这个资源。这和你用不同的锁都可以把相同的一个门锁住是一个道理。
【注意】这个锁是不被某个特定线程所拥有的。一个线程获取了锁,之后任何线程尝试着获取锁,都会失败,包括这个获取了锁的线程自己尝试获取锁。

#创建锁
mutex = threading.Lock()

#锁定
mutex.acquire(blocking = True, timeout = -1) 
"""
返回的是True或者False,分别代表成功和失败。
默认的两个参数:
	1、blocking=True,意思是调用方法的时候没有获取到锁,就会堵塞线程,直到获取到锁为止。
	2、timeout=-1,表示等待获取锁的时间,-1表示一直等待。如果超过timeout设定的时间还没有获取到锁就会返回获取锁失败。
	【注意】如果设定了timeout为正数,则不能设定blocking=False。因为设定了timeout为正数表明等待设定的时间会阻塞线程,和blocking=False是矛盾的。
"""

#释放
mutex.release()

代码举栗:
交替打印ABC,A由一个线程打印 ,B由一个线程打印,C由一个线程打印。

import threading

def work_1():
    for i in range(5):
        mutex1.acquire()
        print("A")
        try:
            mutex2.release()
        except:
            pass

def work_2():
    for i in range(5):
        mutex2.acquire()
        print("B")
        try:
            mutex3.release()
        except:
            pass

def work_3():
    for i in range(5):
        mutex3.acquire()
        print("C")
        try:
            mutex1.release()
        except:
            pass


if __name__ == '__main__':
    mutex1 = threading.Lock()
    mutex2 = threading.Lock()
    mutex3 = threading.Lock()

    t1 = threading.Thread(target=work_1)
    t2 = threading.Thread(target=work_2)
    t3 = threading.Thread(target=work_3)

    t1.start()
    t2.start()
    t3.start()

    t1.join()
    t2.join()
    t3.join()

执行结果:

A
B
C
A
B
C
A
B
C
A
B
C
A
B
C

关于锁还有一些内容,可以参考一下这篇文章:《threading中的锁》

2、函数式创建线程

_thread.start_new_thread(function,args,[kwargs]) 
# function: 线程函数
# args:传递给线程的参数。必须是tuple类型
# []代表可选

例如:

import _thread
import time


def print_curr_time(name,delay):
    """
    用于打印当前时间
    :param name:   线程的名称
    :param delay:  延迟的时间
    :return:
    """
    count = 0
    while count < 5:
        # 让当前休眠。休眠delay的时间
        time.sleep(delay)
        count += 1
        print("{}\t{}".format(name,time.ctime(time.time())))


# 创建线程
try:
    #括号内放的是希望thread去执行的函数
    _thread.start_new_thread(print_curr_time ,("Thread-1",2))
    _thread.start_new_thread(print_curr_time ,("Thread-2",4))
except Exception:
    print("Error: 无法启动线程")

执行结果如下:

Thread-1	Fri Dec 28 17:38:24 2018
Thread-2	Fri Dec 28 17:38:26 2018
Thread-1	Fri Dec 28 17:38:26 2018
Thread-1	Fri Dec 28 17:38:28 2018
Thread-2	Fri Dec 28 17:38:30 2018
Thread-1	Fri Dec 28 17:38:30 2018
Thread-1	Fri Dec 28 17:38:32 2018
Thread-2	Fri Dec 28 17:38:34 2018
Thread-2	Fri Dec 28 17:38:38 2018
Thread-2	Fri Dec 28 17:38:42 2018

故障

Anaconda使用时出现的代理错误解决办法

刚才想用conda创建一个虚拟环境,结果老是出现代理错误,如下图:
1

以前遇到这种情况,一般是换个好点的网速,或者换个镜像。然而这次并没什么用。仔细一看才知道是代理有错。

解决方案如下:
右击桌面的网络图标–>属性–>选择“连接”选项卡;

2

找到局域网设置,把下面的代理服务器勾号去掉,改为“自动检测设置”打勾。应用即可。
3

总是出现python库安装不上的情况

安装python库的时候可能会出现以下情况:

这里写图片描述

勾去代理的方法也不管用,而且安装其他的python库也会出现这种情况。

解决方案1:
找到internet选项重置一下:
这里写图片描述

解决方案2:
换一个连接


Python的函数参数按值还是按引用传递参数?

详情见官方文档:
http://www.runoob.com/python/python-functions.html

这里只说一个我碰到的例子:

def tst(a):
    a.append([1,2,3])
    print('函数tst中的列表a是:',a)
    pass

x = ['q','w','e']
tst(x)
print('函数tst外的列表x是:',x)

输出:

函数tst中的列表a是: ['q', 'w', 'e', [1, 2, 3]]
函数tst外的列表x是: ['q', 'w', 'e', [1, 2, 3]]

从上面现象我们知道,函数在改变形参a的同时居然也把实参x也给改变了!

然后我又去找了一些资料才知道,在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。

然后我又试了一下numpy.array,也是可修改的。

如果想在改变形参的同时又不改变实参,可以这么做:

def tst(a_):
    a = a_.copy()   #copy一下形参接受到的值并赋给变量a
    a.append([1,2,3])
    print('函数tst中的列表a是:',a)
    pass

x = ['q','w','e']
tst(x)
print('函数tst外的列表x是:',x)

输出结果:

函数tst中的列表a是: ['q', 'w', 'e', [1, 2, 3]]
函数tst外的列表x是: ['q', 'w', 'e']
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值