西维蜀黍

【Python】杂 - pyenv 系统 Python 版本管理

Background

Understanding PATH

When you run a command like python or pip, your operating system searches through a list of directories to find an executable file with that name. This list of directories lives in an environment variable called PATH, with each directory in the list separated by a colon:

/usr/local/bin:/usr/bin:/bin

Directories in PATH are searched from left to right, so a matching executable in a directory at the beginning of the list takes precedence over another one at the end. In this example, the /usr/local/bin directory will be searched first, then /usr/bin, then /bin.

  ...


【Python】杂 - macOS 下设置 Python 默认版本

步骤

1 修改可执行文件路径

打开配置文件,指定 python 命令对应的可执行文件路径:

$ open ~/.bash_profile

增加以下:

export PATH=/usr/local/Cellar/python/3.7.4_1/bin:${PATH}

注意,如果是使用 oh-my-zsh,则需要修改添加以上内容到 ~/.zshrc中。

2 配置文件生效

$ source ~/.bash_profile
  ...


【Python】API - 时间表示

表示时间总共有 3 个相关的类

  • datetime.date:表示日期,Attributes: year, month, and day。
  • datetime.time:表示时间,Attributes: hour, minute, second, microsecond, and tzinfo。
  • datetime.dateime:表示日期和时间,Attributes: year, month, day, hour, minute, second, microsecond, and tzinfo。
  • datetime.timedelta:表示一个时间的差值
  ...


【MySQL】MySQL 8 + macOS 错误:Authentication plugin 'caching_sha2_password' cannot be loaded

错误信息

Authentication plugin ‘caching_sha2_password’ cannot be loaded: dlopen(/usr/local/mysql/lib/plugin/caching_sha2_password.so, 2): image not found

这是 MySQL 的问题,不是客户端问题,所以不管是用 Navicat Premium 还是 Sequel Pro 连接 MySQL,会碰到一样的错误。

解决方法

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
  ...


【Python】I/O - 异步 I/O

asyncio

asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。

asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。

asyncio实现Hello world代码如下:

import asyncio

@asyncio.coroutine
def hello():
    print("Hello world!")
    # 异步调用asyncio.sleep(1):
    r = yield from asyncio.sleep(1)
    print("Hello again!")

# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()

@asyncio.coroutine把一个generator标记为coroutine类型,然后,我们就把这个coroutine扔到EventLoop中执行。

hello()会首先打印出Hello world!,然后,yield from语法可以让我们方便地调用另一个generator。由于asyncio.sleep()也是一个coroutine,所以线程不会等待asyncio.sleep(),而是直接中断并执行下一个消息循环。当asyncio.sleep()返回时,线程就可以从yield from拿到返回值(此处是None),然后接着执行下一行语句。

asyncio.sleep(1)看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。

我们用Task封装两个coroutine试试:

import threading
import asyncio

@asyncio.coroutine
def hello():
    print('Hello world! (%s)' % threading.currentThread())
    yield from asyncio.sleep(1)
    print('Hello again! (%s)' % threading.currentThread())

loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
  ...