推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
coolfan
V2EX  ›  Python

我代码动了,我不写了? while 循环莫名其妙运行俩次,找个赛博驱魔师

  •  1
     
  •   coolfan · May 23, 2024 · 8742 views
    This topic created in 902 days ago, the information mentioned may be changed or developed.

    代码在下面

    # pt 文件,pytorch 运行
    
    import sys
    from time import time
    from ultralytics import YOLO
    import cv2
    
    # Load a model
    model = YOLO("yolov8n.pt")  # load an official model
    model = model.to("cuda")
    
    video_path = "C:/Users/username/Desktop/学姐向你发出了约会邀请❤怦然心动❤.1542979357.mp4"
    cap = cv2.VideoCapture(video_path)
    
    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    total_time = 0
    while True:
        ret, frame = cap.read()
        if not ret:
            break  # Exit the loop if no more frames are available
        # frame = cv2.resize(frame, (640, 640))
        start_time = time()
        results = model(frame, verbose=False, classes=[0])
        total_time += time() - start_time
        cv2.imshow("frame", results[0].plot())
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
        # 打印进度
        finished_frames = int(cap.get(cv2.CAP_PROP_POS_FRAMES))
        sys.stdout.write("\r 进度: %.2f %%" % (finished_frames / total_frames * 100))
        sys.stdout.flush()
        # results = model(frame, verbose=False,classes=[0]) CPU FPS:  14.687764775223318
        # results = model(frame, verbose=False,classes=[0]) FPS:  64.14847574515913
        # results = model(frame, verbose=False) FPS:  60.23244793078058
    
        # 2024-05-22 23:32:05 FPS:  60.21048703460454 CUDA
    
    print("\nFPS: ", total_frames / total_time)
    

    这段代码在 22 号还是正常的,输出就是“进度:”滚动,然后最后输出一行 FPS ,cv2.imshow 那三行还没写。

    刚才去洗了个澡,加上了 cv2.imshow 那三行,又跑了一次,输出变成了

    python yolo-torch.py
    C:\Users\username\Documents\code\project\.venv\Lib\site-packages\torch\nn\modules\conv.py:456: UserWarning: Plan failed with a cudnnException: CUDNN_BACKEND_EXECUTION_PLAN_DESCRIPTOR: cudnnFinalize Descriptor Failed cudnn_status: CUDNN_STATUS_NOT_SUPPORTED (Triggered internally at ..\aten\src\ATen\native\cudnn\Conv_v8.cpp:919.)
      return F.conv2d(input, weight, bias, self.stride,
    进度: 99.85 %
    FPS:  75.04395604987724
    进度: 99.85 %
    FPS:  21.148407567206448
    

    终端先是滚动一边进度,非常快,然后打印了一行 FPS ,但是这个时候 cv2 的 imshow 没有展示出来, 在第一个 FPS 打印完之后,又开始滚动输出“进度:”,这次 cv2.imshow 会正常显示,然后最后输出一个 FPS 。

    但是这俩个 FPS 都和 22 号的值差了不少,22 号的时候一直稳定 60 上下

    然后我注释了 # 打印进度下面的三行,输出变成了

    python yolo-torch.py
    C:\Users\username\Documents\code\project\.venv\Lib\site-packages\torch\nn\modules\conv.py:456: UserWarning: Plan failed with a cudnnException: CUDNN_BACKEND_EXECUTION_PLAN_DESCRIPTOR: cudnnFinalize Descriptor Failed cudnn_status: CUDNN_STATUS_NOT_SUPPORTED (Triggered internally at ..\aten\src\ATen\native\cudnn\Conv_v8.cpp:919.)
      return F.conv2d(input, weight, bias, self.stride,
    进度: 99.85 %
    FPS:  72.13356492043005
    
    FPS:  21.089225686164987
    

    为什么啊。我代码一行一行看过去,也看不出来为什么 while 循环会运行俩次,第一次还是我昨天的版本?

    30 replies  •  2024-05-24 09:23:04 +08:00
    metamask
    metamask
    May 23, 2024❤️4
    1
    video_path = "C:/Users/username/Desktop/学姐向你发出了约会邀请❤怦然心动❤.1542979357.mp4"

    代码用这种命名,发生啥 bug 我都不觉得奇怪。
    Gomoku2024
    Gomoku2024
    May 23, 2024
    2
    While True 是会一直运行的,没有适当的退出机制何谈运行两次?说明你的"break"条件,有时不成立,有时成立。
    Gomoku2024
    Gomoku2024
    May 23, 2024
    3
    另外,任何程序,不包括注释,请尽量避免使用中文
    fkdtz
    fkdtz
    May 23, 2024
    4
    @freakxx
    请教这种命名咋了?
    hefish
    hefish
    May 23, 2024❤️1
    5
    会不会是 & 要用 and 代替一下?
    artiga033
    artiga033
    May 23, 2024 via Android
    6
    这种情况一般我会选择进行单步调试
    malaohu
    malaohu
    May 23, 2024
    7
    首先没看你的代码。前几天排查有点类似的情况。
    Flask + 多个线程服务 启动

    main 入口 打印日志 莫名执行 2 次

    原来是开启了调试模式
    dream4ever
    dream4ever
    May 23, 2024
    8
    @malaohu 还能这样,React 的 useEffect 是不是从这里学的,哈哈哈哈
    Shorekeeper
    Shorekeeper
    May 23, 2024 via Android❤️1
    9
    @freakxx 作为一个临时的路径,填什么都是有可能的。只要不明确影响代码(转义之类的问题),这种表述没有意义。
    lx01xsz
    lx01xsz
    May 23, 2024 via iPhone
    10
    这不像是被执行了两次,从第二次进度输出还是 99.85% 就可以看出
    显示较低的 FPS (21.xxx) 应该是 `cv2.imshow` 导致的
    虽然你用了 `sys.stdout.flush()`,但可能 OpenCV 某些操作会引入额外的 delay
    woodfizky
    woodfizky
    May 23, 2024❤️1
    11
    先把代码放函数里,调用的地方放在__main__里调用,这样能排除这个文件被 import 的时候代码被执行一次的情况。

    其他的如果是第三方的东西去跑你这个 py ,那就要看第三方是不是有什么配置。
    woodfizky
    woodfizky
    May 23, 2024❤️17
    12
    另外评论区有些人不知道是不是对中文编码有 ptsd 。

    都 2024 年了,在 windows 平台,用天然支持 utf8 的 python ,读个本地文件用中文路径,能出啥问题呢?
    出问题在读文件那步就已经发现了,不知道在害怕什么。
    Rorysky
    Rorysky
    May 23, 2024
    13
    @woodfizky 水平太差,不了解语言的发展,可能还停留在 py2 的年代
    BruceXu
    BruceXu
    May 23, 2024
    14
    @freakxx 严格来说..这不叫代码的命名.
    这是代码的执行目标的命名,没有任何问题,也无法控制.
    TomatoCLI
    TomatoCLI
    May 23, 2024
    15
    @freakxx 人中文的是字符串,楼上哪些喷的啥意思?字符串都不能输入中文了?又不是变量名用中文
    LDa
    LDa
    May 23, 2024❤️1
    16
    想要知道这个 mp3 是啥
    idealhs
    idealhs
    May 23, 2024❤️3
    17
    @freakxx 感觉你啥也不懂,命名是 video_path 。字符串处理不好就别干了,你这样写出来的软件是那种要求文件和目录不能包含中文和特殊字符的玩意。
    krixaar
    krixaar
    May 23, 2024
    18
    @freakxx #1 一个文件路径,只要能读到能出啥 bug ?
    sijue
    sijue
    May 23, 2024
    20
    在两个 if 中打印,哪个位置打印两次就是第二次循环没拦住
    AFuture
    AFuture
    May 23, 2024
    22
    你想问 为什么加了 cv2.imshow 导致 FPS 降低么?
    应该是 waitKey 时同步的关系,等待输入的时候,进程卡在那,但是 FPS 的统计时长是增加的。
    AFuture
    AFuture
    May 23, 2024
    23
    @AFuture 无视无视 。。
    deemoe
    deemoe
    May 23, 2024
    24
    @sijue #20 不像,仔细观察楼主贴的 log 里打印两次的百分比是一样的
    Anarchy
    Anarchy
    May 23, 2024
    25
    @woodfizky #12 Python 是支持可是 OpenCV 可不一定支持
    lostsummer
    lostsummer
    May 23, 2024❤️1
    26
    你将主要运行代码放到

    if __name__ == "__main__":

    下面。

    我没有 windows 环境去验证,但我猜你是遇到了 python 多进程在 windows 环境的一个常见问题。( cv2.imshow 开窗口时可能会 fork 一个子进程)

    原因解释看下: https://zhuanlan.zhihu.com/p/616746911 #七、
    artiga033
    artiga033
    May 23, 2024 via Android❤️2
    27
    @Amose2024 都 2024 年了,对于一个支持 Unicode 标识符的编程语言,您猜怎么着,我不但能用中文,甚至还能用 emoji 和阿拉伯语
    Freakr
    Freakr
    May 23, 2024
    28
    @artiga033 Python 里面不用 emoji 作为标识符吧
    vivisidea
    vivisidea
    May 23, 2024
    29
    @lostsummer 我也是这个猜测,估计是起了进程,又运行了一遍

    可以试试在 while True: 前面加上打印当前进程号的代码即可验证

    import os

    # 获取当前进程 ID
    current_process_id = os.getpid()

    # 打印当前进程 ID
    print(f"当前进程 ID: {current_process_id}")
    purplemystic
    purplemystic
    May 24, 2024
    30
    @Amose2024 中文注释也遇到过问题, C++里面, 中文注释导致编译失败
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1016 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 69ms · UTC 22:37 · PVG 06:37 · LAX 14:37 · JFK 17:37
    ♥ Do have faith in what you're doing.