周报@2023-04-26

浏览器获取设备的逻辑 CPU 核心数

现代的 Web 浏览器提供了一些 API 来获取设备的硬件信息,包括 CPU 核心数。其中,navigator.hardwareConcurrency 是一个只读属性,可以获取设备的逻辑 CPU 核心数。

逻辑 CPU 核心数指的是 CPU 能够并行处理的任务数,这个数值通常等于物理 CPU 核心数乘以超线程技术的因子(如果 CPU 支持超线程)。例如,一台四核八线程的 CPU,在 navigator.hardwareConcurrency 中就会返回 8。

input type="file"

<input type="file" name="picfile" multiple /> 中 multiple 属性可以控制文件是否可以多选。

JSON.stringify 的 replacer 的应用场景

JSON.stringify 方法的第二个参数 replacer 是一个可选的函数或数组,用于控制序列化过程中哪些属性应该被包含或者转换。

在使用 replacer 函数时,函数会在序列化过程中遍历要序列化的对象中的每一个键值对,每一个键值对都会传递给 replacer 函数进行处理,根据返回值的不同,来决定键值对是否要包含在序列化结果中,以及如何进行转换。

replacer 函数的主要应用场景有以下几种:

  1. 过滤属性:可以使用 replacer 函数过滤掉一些不必要的属性,只序列化需要的属性,这样可以减小序列化结果的体积,提高传输效率。
  2. 转换属性:可以使用 replacer 函数对属性值进行转换,例如将日期类型转换为字符串类型,或者对一些特殊的类型进行自定义的转换。
  3. 限制序列化深度:在嵌套的对象或数组中,可以使用 replacer 函数来限制序列化的深度,避免出现循环引用或者爆栈的问题。
  4. 自定义序列化:replacer 函数可以根据实际需求来自定义序列化过程,实现更加灵活的序列化操作,比如将对象序列化为 XML 格式。

需要注意的是,在使用 replacer 函数时,需要仔细设计函数的逻辑,确保序列化结果符合预期,并且不会影响到原始数据。

当使用 JSON.stringify 方法时,我们可以通过传递一个 replacer 函数或数组来控制序列化过程中哪些属性需要包含或者转换。

以下是一些使用 replacer 函数或数组的例子:

过滤属性

javascript
1const obj = {
2  name: 'Tom',
3  age: 20,
4  sex: 'male'
5};
6
7const replacer = (key, value) => {
8  // 只序列化名字和年龄属性
9  if (key === 'name' || key === 'age') {
10    return value;
11  } else {
12    return undefined; // 过滤掉其他属性
13  }
14};
15
16const jsonString = JSON.stringify(obj, replacer);
17console.log(jsonString); // 输出 {"name":"Tom","age":20}

转换属性

javascript
1const obj = {
2  name: 'Tom',
3  age: 20,
4  birthday: new Date(2000, 1, 1)
5};
6
7const replacer = (key, value) => {
8  if (key === 'birthday') {
9    return value.toLocaleDateString(); // 将日期类型转换为字符串类型
10  } else {
11    return value;
12  }
13};
14
15const jsonString = JSON.stringify(obj, replacer);
16console.log(jsonString); // 输出 {"name":"Tom","age":20,"birthday":"2/1/2000"}

限制序列化深度

javascript
1const obj = {
2  name: 'Tom',
3  age: 20,
4  address: {
5    province: 'Beijing',
6    city: 'Beijing',
7    district: 'Haidian'
8  }
9};
10
11const replacer = (key, value) => {
12  if (key === 'address') {
13    // 只序列化省份和城市属性,忽略区县属性
14    return {
15      province: value.province,
16      city: value.city
17    };
18  } else {
19    return value;
20  }
21};
22
23const jsonString = JSON.stringify(obj, replacer);
24console.log(jsonString); // 输出 {"name":"Tom","age":20,"address":{"province":"Beijing","city":"Beijing"}}

自定义序列化

javascript
1const obj = {
2  name: 'Tom',
3  age: 20
4};
5
6const replacer = (key, value) => {
7  if (key === '') { // 根节点,返回 XML 格式的字符串
8    return `<?xml version="1.0" encoding="UTF-8"?>\n<root>${value}</root>`;
9  } else if (typeof value === 'string' || typeof value === 'number') { // 基本类型,直接返回
10    return value;
11  } else { // 对象或数组,递归调用 replacer 函数
12    let str = '';
13    for (let prop in value) {
14      str += `<${prop}>${replacer(prop, value[prop])}</${prop}>`;
15    }
16    return str;
17  }
18};
19
20const jsonString = JSON.stringify(obj, replacer, '');
21console.log(jsonString); // 输出 <?xml version="1.0" encoding="UTF-8"?><root><name>Tom</name><age>20</age></root>

注意,在使用 replacer 函数时,需要确保函数的逻辑正确,否则会影响到序列化结果。

对 key 进行排序

你也可以使用 JSON.stringify() 方法的第二个参数 replacer 来实现按照 key 进行排序的功能。replacer 参数是一个函数,它接受两个参数:属性名和属性值。通过在 replacer 函数中返回属性值,我们可以控制哪些属性将包含在输出的 JSON 字符串中。以下是一个例子:

javascript
1const jsonObj = {
2  b: 2,
3  c: 3,
4  a: 1
5};
6
7const sortedJsonStr = JSON.stringify(jsonObj, (key, value) => {
8  if (typeof value === 'object' && value !== null) {
9    // 如果 value 是对象,则使用数组对其进行排序
10    return Object.entries(value)
11      .sort((a, b) => a[0].localeCompare(b[0]))
12      .reduce((obj, [k, v]) => ({ ...obj, [k]: v }), {});
13  } else {
14    // 如果 value 不是对象,则直接返回
15    return value;
16  }
17});
18
19console.log(sortedJsonStr); // {"a":1,"b":2,"c":3}

在这个例子中,我们将 jsonObj 对象和一个回调函数传递给 JSON.stringify() 方法。在回调函数中,我们首先检查 value 是否为一个对象,如果是,则使用 Object.entries() 方法将其转换为数组,然后按照 key 进行排序。最后,我们使用 reduce() 方法将排序后的数组转换回对象。如果 value 不是对象,则直接返回。这样,我们可以确保在 JSON 字符串中按照 key 进行排序。

请注意,这种方法会影响 JSON 字符串中所有的对象属性,包括嵌套的对象。如果你只想对某些属性按照 key 进行排序,可以在 replacer 函数中添加更多的逻辑来控制哪些属性进行排序。

wget

基本的 wget 命令格式如下:

bash
1wget -O /path/to/local/file.ext https://example.com/path/to/remote/file.ext

请将 /path/to/local/file.ext 替换为您希望保存文件的本地路径,将 https://example.com/path/to/remote/file.ext 替换为您要下载的文件的 URL。

例如,如果您希望从 GitHub 下载一个文件并将其保存到本地的 myfile.txt,您可以使用以下命令:

bash
1wget -O myfile.txt https://raw.githubusercontent.com/user/repo/branch/path/to/file.txt

请根据实际情况替换文件路径和 URL。

pip 相关问题

使用腾讯云镜像源加速pip

临时使用

运行以下命令以使用腾讯云pypi软件源:

js
1pip install -i https://mirrors.cloud.tencent.com/pypi/simple <some-package>

注意:必须加上路径中的simple

设为默认

升级 pip 到最新的版本 (>=10.0.0) 后进行配置:

js
1pip install pip -U
2pip config set global.index-url https://mirrors.cloud.tencent.com/pypi/simple

您也可以临时使用镜像来升级 pip:

js
1pip install -i https://mirrors.cloud.tencent.com/pypi/simple --upgrade pip

pip install 的 package 不是最新版本

如果您发现 pip install 命令没有安装最新版本的包,可以尝试以下方法:

  1. 更新 pip:旧版本的 pip 可能无法识别新版本的包。运行以下命令来更新 pip:

    bash
    1python -m pip install --upgrade pip
  2. 清除 pip 缓存:pip 缓存可能会导致安装过时的包版本。您可以使用 --no-cache-dir 选项跳过缓存:

    bash
    1pip install --no-cache-dir package-name
  3. 检查 PyPI:确保您要安装的最新版本的包已发布到 PyPI https://pypi.org/ 在网站上搜索您需要的包,查看最新版本。

  4. 检查 Python 版本兼容性:确保您的 Python 版本与要安装的包的最新版本兼容。有时,最新版本的包可能不支持较旧的 Python 版本。这种情况下,您需要更新 Python 或安装较旧的包版本。

  5. 虚拟环境:使用虚拟环境可以确保您在干净的环境中安装包。这有助于避免因其他包或系统设置导致的问题。要创建并激活虚拟环境,请运行以下命令:

    bash
    1python -m venv myenv
    2source myenv/bin/activate  # 在 Windows 上使用 `myenv\Scripts\activate`

    在激活虚拟环境后,尝试再次安装所需的包。

其实问题原因时依赖冲突,pip install --use-deprecated=legacy-resolver lama-cleaner==1.1.2 rembg==2.0.35

python:3.10-slim 报错 source: not found

当您在 Docker 中使用基于 Alpine Linux 或其他精简的基础镜像(例如,python:3.x-slimnode:14-slim)时,可能会遇到 "source: not found" 错误。这是因为这些精简镜像使用 ash 作为默认 shell,而不是更常见的 bash,而 source 命令在 ash 中不可用。

您可以使用以下方法解决这个问题:

  1. 使用 . 运算符代替 source 命令。在 ash shell 中,. 运算符与 source 命令的功能相同。将 Dockerfile 中的 source 替换为 .,例如:

    bash
    1RUN . /path/to/your/script.sh
  2. 更改基础镜像以使用 bash 作为默认 shell。首先,您需要确保 bash 已安装。在 Dockerfile 中添加以下行以安装 bash 并将其设置为默认 shell:

    css
    1RUN apk add --no-cache bash
    2SHELL ["/bin/bash", "-c"]

    然后,您可以像在其他镜像中一样使用 source 命令。

请选择其中一个方法来解决 "source: not found" 错误,并根据您的需求和基础镜像调整 Dockerfile。