关于在使用anaconda/python过程中遇到的问题和解决方法。
1. Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问
在windows下使用pip升级包的时候,出现了这个错误。根据提示,使用--user或者是权限问题。测试权限不行,解决方法:
pip install --user --upgrade package
2. Anaconda 创建/删除虚拟环境(Linux)
在python中有时需要不同的环境,或者在服务器之间迁移环境(尤其是内网环境),使用虚拟环境就会非常方便。conda常用命令地址。创建虚拟环境pip和conda都可,但是建议使用conda,小部分情况下pip创建的虚拟环境不适用。
创建环境 conda create --name env_test python=3.6
激活环境 source activate env_test
退出环境 source deactivate env_test
移除环境 conda remove --name env_test --all 这里建议使用--name,使用-n可能无效
虚拟环境安装包 conda install --name env_test package_name
卸载虚拟环境安装包 conda remove --name env_test package_name
或者使用pip安装 pip install package_name -i https://pypi.tuna.tsinghua.edu.cn/simple/ (使用了清华镜像,不用也可,但是可能比较慢)
查看安装包 conda list
查看存在的虚拟环境 conda env list
3. error tokenizing data. C error: Calling read(nbytes) on source failed.try engine='python'
今天在使用pd.read_csv读取文件的时候,报了这么一个错。分析原因如下:
因为使用的是不可见字符作为分隔符,看是否是数据里面含有 \ 等特殊字符导致的,发现不是这个原因。
engine参数,也不是这个问题。
因为是直接读取的目录,打印实际读取的文件,发现有一个隐藏文件,删掉即可。
4. 禁止conda自动更新python版本
在使用conda install package安装包的时候,有时候会遇到conda会自动把python也更新到最新的版本,例如 python3.6更新到python3.7,这显然不是我们想要的。其实在安装包的时候指定已有python版本就行了:
conda install package python=3.6.5
5. sqlite3.OperationalError: database or disk is full
在打开jupyter或者python文件的时候,有时候会出现sqlite3.OperationalError: database or disk is full的错误情况,这种错误一般是由于磁盘不足导致的,去jupyter所在用户的 ~/ 目录下,查看该目录是否还有可用空间,清理一下就可以了。
6. HTTPSConnectionPool(host='pypi.tuna.tsinghua.edu.cn', port=443): Read timed out
pip install 出现下面问题:
pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='pypi.tuna.tsinghua.edu.cn', port=443): Read timed out.
一般出现在安装包比较大或者网络不好的时候,添加超时参数就可以了。
pip install tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple/ --timeout 1000
7. jupyter notebook保存为py文件
(1)第一种方法,直接点击jupyter中的 File --> Download as --> Python(.py)即可。
(2)使用魔法函数,在代码块首行添加 %%writefile test.py 运行后,即可把当前代码块程序保存为test.py文件,新的代码块如果也使用魔法函数保存到同一文件中,会覆盖之前的内容。
如果需要在Jupyter中运行py文件,可以执行 %run test.py 即可。
8. TypeError: can't pickle _thread._local objects
问题如题,这种现象一般是出在python多进程里面使用了自定义类的现象。但是我的问题是出现在python连接数据库的时候。
python使用create_engine连接数据库,然后通过多进程处理数据,每个进程里面都会通过pandas使用数据库引擎读取数据。虽然多进程会拷贝父进程的变量空间,但是engine的连接其实是同一个,导致出现下面问题:
File "/root/miniconda3/lib/python3.7/site-packages/pandarallel/pandarallel.py", line 302, in
for index, (input_file, output_file, chunk_length) in enumerate(
File "/root/miniconda3/lib/python3.7/site-packages/dill/_dill.py", line 304, in dumps
dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
File "/root/miniconda3/lib/python3.7/site-packages/dill/_dill.py", line 276, in dump
Pickler(file, protocol, **_kwds).dump(obj)
File "/root/miniconda3/lib/python3.7/site-packages/dill/_dill.py", line 498, in dump
StockPickler.dump(self, obj)
File "/root/miniconda3/lib/python3.7/pickle.py", line 437, in dump
self.save(obj)
File "/root/miniconda3/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/root/miniconda3/lib/python3.7/site-packages/dill/_dill.py", line 1496, in save_function
obj.__dict__, fkwdefaults), obj=obj)
File "/root/miniconda3/lib/python3.7/pickle.py", line 638, in save_reduce
save(args)
File "/root/miniconda3/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/root/miniconda3/lib/python3.7/pickle.py", line 786, in save_tuple
save(element)
File "/root/miniconda3/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/root/miniconda3/lib/python3.7/pickle.py", line 786, in save_tuple
save(element)
File "/root/miniconda3/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/root/miniconda3/lib/python3.7/site-packages/dill/_dill.py", line 1227, in save_cell
pickler.save_reduce(_create_cell, (f,), obj=obj)
File "/root/miniconda3/lib/python3.7/pickle.py", line 638, in save_reduce
save(args)
File "/root/miniconda3/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/root/miniconda3/lib/python3.7/pickle.py", line 771, in save_tuple
save(element)
File "/root/miniconda3/lib/python3.7/pickle.py", line 549, in save
self.save_reduce(obj=obj, *rv)
File "/root/miniconda3/lib/python3.7/pickle.py", line 662, in save_reduce
save(state)
File "/root/miniconda3/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/root/miniconda3/lib/python3.7/site-packages/dill/_dill.py", line 990, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/root/miniconda3/lib/python3.7/pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "/root/miniconda3/lib/python3.7/pickle.py", line 882, in _batch_setitems
save(v)
File "/root/miniconda3/lib/python3.7/pickle.py", line 549, in save
self.save_reduce(obj=obj, *rv)
File "/root/miniconda3/lib/python3.7/pickle.py", line 662, in save_reduce
save(state)
File "/root/miniconda3/lib/python3.7/pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "/root/miniconda3/lib/python3.7/site-packages/dill/_dill.py", line 990, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "/root/miniconda3/lib/python3.7/pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "/root/miniconda3/lib/python3.7/pickle.py", line 882, in _batch_setitems
save(v)
File "/root/miniconda3/lib/python3.7/pickle.py", line 524, in save
rv = reduce(self.proto)
TypeError: can't pickle _thread._local objects
解决方法也很简单,子进程不使用同一个数据库连接就可以了。其实create_engine本身就是一个连接池工具,在父进程中定义create_engine:
engine = create_engine(..., encoding="UTF-8", pool_size=pool_size, max_overflow=5)
然后在子进程中获取连接:
conn = engine.connect() # 从连接池中获取连接
.......
.......
conn.close() # 连接放回连接池,并没有断掉,可重复使用
9. Pycharm打开项目看不到项目文件
这种一般是从其他地方拷贝的工程文件或者是git clone的文件,导致的原因主要是pycharm版本不一致导致的,只需要删除项目里面的 .idea 目录即可(注意可能是隐藏目录)。另外,最好在git提交程序的时候配置 .gitignore 不要提交 .idea 文件。
10. python进程池不执行
python进程池的相关API非常简单,但是在调用的时候始终不执行,花了半天时间调试,总结如下:
from multiprocessing import Pool
import os,time,random
def worker(msg):
t_start = time.time()
print("%s开始执行,进程号为%d"%(msg,os.getpid()))
time.sleep(random.random()*2)
t_stop = time.time()
print(msg,"执行完毕,耗时%0.2f"%(t_stop-t_start))
def pool_call_back(res):
print(res)
def pool_error_back(res):
print(res)
def main():
po=Pool(3) #定义一个进程池,最大进程数3
for i in range(0,10):
po.apply_async(func=worker, args=(i,), callback=pool_call_back, error_callback=pool_error_back)
print("----start----")
po.close() #关闭进程池,关闭后po不再接收新的请求
po.join() #等待po中所有子进程执行完成,必须放在close语句之后
print("-----end-----")
(1)子任务一个参数的问题:上面程序在提交子进程的时候,传递了一个参数 i,这里尤其需要注意python进程池传参是按照元祖传参,元祖在只有一个元素的情况下,必须在元素后加逗号,否则会出错,就不会执行子进程。
(2)函数嵌套:一般建议把子进程的代码块单独放在一个函数中,然后在进程池中调用。这里需要注意尽量不要把子进程代码块函数嵌套在主函数中,例如上面程序把worker函数定义在main函数内部,可能也会导致不执行的问题,具体原因还没有分析。
(3)参数序列化:在apply_async中传递给子进程的参数一定要可pickle,可以理解为可序列化,如果参数不能序列化,也会出错不执行。我就是遇到了这个问题,建立了一个数据库连接池,每次传递一个数据库连接给子进程,连接不能序列化导致出错,最后通过俄式方法:定义全局共享变量解决。
(4)上面说了一些出错的情况,但是在使用中会发现程序都是正常执行,没有任何报错信息,就是不执行子程序代码块,这是因为apply_async的错误信息需要定义一个出错的回调函数,例如上面程序的 pool_error_back 函数,比较坑的是这个参数是可选的,而网上的例子 95% 以上都没有定义这个参数,所以一般会非常难以发现。这个时候可以通过多进程测试,不要使用进程池就会出现错误信息。
11. Received unregistered task of type
使用celery调度任务出现 Received unregistered task of type 错误信息。这种情况主要是由于任务未注册导致的,首先看一下import配置项里面有没有加路径配置信息,然后检查任务装饰器注册任务的时候和调度里面的任务名字是否一致,比如一边写了 task,另一边写了 tasks,多了一个s。