brew 升级和执行 brew cleanup 之后 Python virtualenv 的路径总是出问题,今天算是把问题找到了,但是却没找到好的解决办法…… 最终的解决方案是将所有的 virtualenv 删除重装。急着修复问题的可以不看中间的尝试直接拉到最下面。

以其中一个虚拟环境为例:

Shell

1

2

$ ll ~/.local/venvs/pylint/.Python

lrwxr-xr-x  1 laixintao  staff  80 Mar 26 17:04 /Users/laixintao/.local/venvs/pylint/.Python@ -> /usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6/Python

可以看到之前有一个 .Python 文件是软链接到 brew 安装的 Python3 的,以这次升级为例,3.6.4_4 这个版本已经不存在了,目前有的是 /usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/bin/python3.6 ,本打算将新的路径作为 .Python 的软连接:

Shell

1

ln -sf /usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/Python ~/.local/venvs/pylint/.Python

但发现现在 pylint 是可以执行了,但是找不到依赖的包,于是又写了一个脚本,打算找到其所有的软连接,全都链接到最新的 3.6.5 版本中:

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

# -*- coding: utf-8 -*-

import subprocess

if __name__ == '__main__':

    out = subprocess.check_output("find ~/.local/venvs/twine -type l | xargs ls -la | awk '{if ($11) print $9, $11}'", shell=True)

    for line in out.decode().split('\n'):

        if not line:

            continue

        target, old_source = line.split(' ')

        new_source = old_source.replace('3.6.4_4', '3.6.5')

        print("old_source: {}, new_source:{}, target: {}".format(old_source, new_source, target))

        subprocess.run("ln -sf {} {}".format(new_source, target), shell=True)

发现执行完之后还是找不到相关的包:

Python

1

2

3

4

Traceback (most recent call last):

  File "/Users/laixintao/.local/bin/pylint", line 7, in <module>

    from pylint import run_pylint

ModuleNotFoundError: No module named 'pylint'

没办法,先重新建一下 virtualenv 吧,以前是这样处理的,应该也是最稳的方法了。

我的 Python 命令行工具是用 pipsi 安装的,这个工具和 pip 的不同是: 它不会把模块装到系统 Python 而是每一个包新建一个 virtualenv ,然后在这个 virtualenv 中安装,然后链接 bin 的 Path。将所有 pipsi 安装的工具重装的命令如下:

pipsi list | grep -Eo ‘”(.*)”‘ | cut -c2- |rev | cut -c2- | rev | xargs -I {} — zsh -c ‘pipsi uninstall {} –yes ; pipsi install –python python3 {}|| pipsi install {}’

解释如下(按照颜色匹配):

  1. 打印出所有package,比如 “pylint”
  2. 砍掉第一个双引号,翻转,砍掉第一个双引号,再翻转(实际上就是去掉双引号)
  3. 将前面得到的干净包名传给下面的子命令,其中 {} 将被替换成包名
  4. 先卸载,再尝试用 python3 安装,如果失败改用 python2 安装

pipsi 的包就重建好了。virtualenv 里面的工作用的 env 自动重建了没什么意义,因为各个 env 的依赖都是根据项目的 requirements.txt 安装好的。还是用到什么再次重建什么吧。