小编Oli*_*çon的帖子

在 Python3 中构建模块异常的最佳实践

假设我有一个文件夹结构像这样的项目。

/project
    __init__.py
    main.py
    /__helpers
        __init__.py
        helpers.py
        ...
Run Code Online (Sandbox Code Playgroud)

该模块helpers.py定义了一些异常并包含一些引发该异常的方法。

# /project/__helpers/helpers.py

class HelperException(Exception):
    pass

def some_function_that_raises():
    raise HelperException
Run Code Online (Sandbox Code Playgroud)

另一方面,我的main.py模块定义了自己的异常并导入了可能从helpers.py.

# /projects/main.py

from project.__helpers.helpers import some_function_that_raises

class MainException(Exception):
    pass
Run Code Online (Sandbox Code Playgroud)

现在,from project.__helpers.helpers import HelperException如果用户想要捕获该异常,我不希望用户必须这样做。能够从引发异常的公共模块导入异常会更有意义。

但我不能只是移动HelperExceptionmain.py,这会创建一个循环导入。

允许用户导入所有异常的最佳方法main.py/__helpers什么?

python exception circular-dependency python-3.x

6
推荐指数
1
解决办法
1301
查看次数

为什么 str.find 在没有找到子字符串时返回 -1?

在另一个询问如何在不使用 str.split 的情况下获取字符串的第一个单词的问题中,一些用户提出了以下想法。

word = s[:s.find(' ')]
Run Code Online (Sandbox Code Playgroud)

只要字符串s包含空格,它就会起作用。尽管如果它不包含一个,这会默默地失败。

s = 'foo'
word = s[:s.find(' ')] # 'fo'
Run Code Online (Sandbox Code Playgroud)

这是因为当未找到子字符串时str.find返回。-1

由于以下原因,这似乎是一个奇怪的设计选择。

  1. -1实际上是一个正确的索引

  2. 解释为 a bool,它在上下文中没有任何有用的含义

  3. None似乎是一个更好的候选者(并且将使上面的代码工作)

是否有一个好的设计原因或用例为什么-1选择作为返回值str.find而不是None当没有找到子字符串时?

python string

6
推荐指数
1
解决办法
697
查看次数

为什么检查会从继承超类的类返回不同的行?

在试图弄清楚是否使用@decorator语法调用函数时,我们意识到inspect在查看从超类继承的装饰类时会有不同的行为.

在Windows 10下,CPython 3.6.2发现了以下行为.

它也在Linux 64位下在CPython 3.7.0中重现.

import inspect

def decorate(f):
    lines = inspect.stack()[1].code_context
    print(f.__name__, lines)

    return f

@decorate
class Foo:
    pass

@decorate
class Bar(dict):
    pass
Run Code Online (Sandbox Code Playgroud)

产量

Foo ['@decorate\n']
Bar ['class Bar(dict):\n']
Run Code Online (Sandbox Code Playgroud)

为什么继承改变了行为inspect

python decorator inspect python-decorators python-3.6

6
推荐指数
1
解决办法
71
查看次数

如何创建在继承操作下关闭的类型?

在数学意义上,如果操作总是返回集合本身的成员,则在操作下关闭集合(或类型).

这个问题是关于在从超类继承的所有操作下关闭一个类.

考虑以下课程.

class MyInt(int):
    pass
Run Code Online (Sandbox Code Playgroud)

由于__add__没有被覆盖,因此不会因此而关闭.

x = MyInt(6)
print(type(x + x))  # <class 'int'>
Run Code Online (Sandbox Code Playgroud)

使类型关闭的一种非常繁琐的方法是手动转换返回intto 的每个操作的结果MyInt.

在这里,我使用元类自动化该过程,但这似乎是一个过于复杂的解决方案.

import functools

class ClosedMeta(type):
    _register = {}

    def __new__(cls, name, bases, namespace):
        # A unique id for the class
        uid = max(cls._register) + 1 if cls._register else 0

        def tail_cast(f):
            @functools.wraps(f)
            def wrapper(*args, **kwargs):
                out = f(*args, **kwargs)
                if type(out) in bases:
                    # Since the class does not exist yet, we will recover …
Run Code Online (Sandbox Code Playgroud)

python oop containers metaclass python-3.x

6
推荐指数
1
解决办法
157
查看次数

通过数学表达式拆分Python字符串

我有很多Python字符串如"A7*4","Z3+8","B6 / 11",和我想要拆分这些字符串,这样他们将在一个列表,格式["A7", "*", "4"],["B6", "/", "11"]等我已经使用了很多不同的方法分割,但我想我需要只需执行有数学符号的分割,例如/,*,+,-.我还需要删除空白.

目前我正在使用re.split(r'(\D)', "B6 / 11")返回的代码['', 'B', '6', ' ', '', '/', '', ' ', '11'].相反,我想回来["B6", "/", "11"].

python regex string split

5
推荐指数
2
解决办法
4204
查看次数

列出 Python 日期时间倒计时(以复数形式表示)

我一直在尝试创建一个函数,使用正确的单词列出日期之间的时间,特别是我希望它能够解释复数。我知道我可以通过 if 语句运行所有数字来做到这一点,但我真的希望找到一种更有效的方法来实现我的目标。

IE:我希望221 days, 1:17:06.996068datetime返回,因为221 days, 1 hour, 17 minutes, and 6.99 seconds.它很重要,它在适当的时候表示日/小时/分钟/秒或天/小时/分钟/秒。

我的代码示例片段:

from datetime import datetime as dt

now = dt.now(tz=None) # Current local computer time
test = dt(2018,3,25,23,0,0) # March 25th, 2018 23h 0m 0s
countdown = test - now
print(countdown) # 2 days, 1:45:00.685739
# Desired outcome: 2 days, 1 hour, 45 minutes, 0.68 seconds.
Run Code Online (Sandbox Code Playgroud)

有没有一种函数可以有效地在单数或复数时间之间进行标记?

python datetime date python-3.x

5
推荐指数
1
解决办法
582
查看次数

在列表中的另一个值之后插入一个值

我想要一个函数调用insert_after,它将获取一个列表和两个值(search_valuevalue).

然后应该value在第一次出现后插入功能search_value

如果search_value在列表中,然后将其添加到年底.我想用一个try...except声明来做这件事.

例如,如果列表是:

myList = [4,2,6,7,8,1], 
Run Code Online (Sandbox Code Playgroud)

那么函数调用:

insert_after(myList, 7, 5)
Run Code Online (Sandbox Code Playgroud)

应该返回:

[4,2,6,7,5,8,1]
Run Code Online (Sandbox Code Playgroud)

我已经尝试过了,但即使我指定了索引,我的值也会一直插入到列表的末尾.

def insert_after(list1, search_value, value):
    try:
        for i in list1:
            if i == search_value:
                list1.insert(search_value+1,value)
            else:
                list1.insert(len(list1)+1,value)
    except:
        list1.insert(len(list1)+1,value)
Run Code Online (Sandbox Code Playgroud)

python list

5
推荐指数
1
解决办法
115
查看次数

为什么这个单例实现"不是线程安全的"?

1. @Singleton装饰

我找到了一种优雅的方法来装饰Python类来实现它singleton.该类只能生成一个对象.每次Instance()调用都返回相同的对象:

class Singleton:
    """
    A non-thread-safe helper class to ease implementing singletons.
    This should be used as a decorator -- not a metaclass -- to the
    class that should be a singleton.

    The decorated class can define one `__init__` function that
    takes only the `self` argument. Also, the decorated class cannot be
    inherited from. Other than that, there are no restrictions that apply
    to the decorated class.

    To get the singleton instance, use the …
Run Code Online (Sandbox Code Playgroud)

python singleton multithreading python-3.x python-3.6

5
推荐指数
2
解决办法
4507
查看次数

在异步任务之间自由切换的正确方法是什么?

假设我有一些异步运行的任务。它们可能是完全独立的,但我仍然想设置 tak 将暂停的点,以便它们可以同时运行。

并发运行任务的正确方法是什么?我目前正在使用await asyncio.sleep(0),但我觉得这会增加很多开销。

import asyncio

async def do(id, amount):
    for i in range(amount):
        # Do some time-expensive work
        print(f'{id}: has done {i}')

        await asyncio.sleep(0)

    return f'{id}: done'

async def main():
    res = await asyncio.gather(do('Task1', 5), do('Task2', 3))
    print(*res, sep='\n')

loop = asyncio.get_event_loop()

loop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)

输出

Task1: has done 0
Task2: has done 0
Task1: has done 1
Task2: has done 1
Task1: has done 2
Task1: done
Task2: done
Run Code Online (Sandbox Code Playgroud)

如果我们使用简单的生成器,emptyyield会在没有任何开销的情况下暂停任务流,但 emptyawait是无效的。

在没有开销的情况下设置此类断点的正确方法是什么?

python asynchronous python-3.x python-asyncio

5
推荐指数
1
解决办法
1105
查看次数

如何在超时的情况下动态导入不安全的 Python 模块?

我需要动态加载几个可能不安全的模块以进行测试。

关于安全性,我的脚本由低访问权限的用户执行。

尽管如此,我仍然需要一种方法来优雅地使导入过程超时,因为我不能保证模块脚本会终止。例如,它可以包含对input或无限循环的调用。

我目前正在使用Thread.joina timeout,但这并不能完全解决问题,因为脚本在后台仍然存在并且无法杀死线程。

from threading import Thread
import importlib.util

class ReturnThread(Thread):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._return = None

    def run(self):
        if self._target is not None:
            self._return = self._target(*self._args, **self._kwargs)

    def join(self, *args, **kwargs):
        super().join(*args, **kwargs)
        return self._return

def loader(name, path):
    spec = importlib.util.spec_from_file_location(name, path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module) # This may run into an infinite loop
    return module

module_loader = ReturnThread(loader, ('module_name', 'module/path'))
module_loader.start()
module = module_loader.join(timeout=0.1)

# The thread might …
Run Code Online (Sandbox Code Playgroud)

python import module python-3.x python-importlib

5
推荐指数
1
解决办法
676
查看次数