周报@2023-04-26

浏览器获取设备的逻辑 CPU 核心数, 如何限制 input file 可选数量

浏览器获取设备的逻辑 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软件源:

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

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

设为默认

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

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

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

pip 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。