Azure管道找不到用户创建的Python模块

06odsfpq  于 2023-10-21  发布在  Python
关注(0)|答案(3)|浏览(115)

我正在尝试使用Azure DevOps从Python模块运行测试。我已经建立了一个管道来构建一个yml文件,也使用了经典编辑器。我得到一个错误,我的模块名称对我的进口是不正确的。当我在本地运行它时,它工作得很好。

我的回购结构:

我正在使用此命令作为批处理文件运行测试:

  • cd测试用例 *
  • pytest -v test_msoffice.py*
    并给出错误:
______________________ ERROR collecting test_msoffice.py ______________________
ImportError while importing test module 'D:\a\1\s\testcases\test_msoffice.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test_msoffice.py:7: in <module>
    from util import utility_method_class
E   ModuleNotFoundError: No module named util

谁来帮帮我。

kxxlusnw

kxxlusnw1#

前两天我也出现了同样的症状。我假设你的软件包在本地一个名为 “util” 的目录中,有(或者根据你的评论没有)一个__init__.py文件。这使得python将该目录下的所有模块识别为属于utils包。(从Python 3.something开始,python将管理对本地目录结构的“命名空间引用”,而不使用__init__.py)在Pipeline代理上,代码直接复制到D:\a\1\s\中-因此python将认为包被称为 “s”
我找到了以下解决办法:在管道中包含一个脚本,将源代码移动到一个新的适当命名的目录中,然后在那里测试它
我的Pipeline YAML看起来像这样。它基于这样的假设:你的ADO项目和你的包的名字一样--所以在你的例子中是 “util”,并且是为ubuntu / bash设置的。如果你必须在windows代理上测试,那么脚本需要移植,或者你可以切换到ubuntu代理并复制整个脚本。

# Python package
# Create and test a Python package on multiple Python versions.
# Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and more:
# https://learn.microsoft.com/azure/devops/pipelines/languages/python

trigger:
- azure-pipelines
- master
- pipeline/*

variables:
  PythonPackagePath: ORIGINALVALUE

pool:
  vmImage: ubuntu-latest
strategy:
  matrix:
    # Python27:
    #   python.version: '2.7'
    # Python35:
    #  python.version: '3.5'
    # Python36:
    #   python.version: '3.6'
    # Python37:
    #   python.version: '3.7'
    Python310:
      python.version: '3.10'

steps:
- task: UsePythonVersion@0
  inputs:
    versionSpec: '$(python.version)'
  displayName: 'Use Python $(python.version)'

- script: |
    cd $(System.DefaultWorkingDirectory)
    export ParentDir=${PWD%/*}

    echo Setting PythonPackagePath to $ParentDir/$(System.TeamProject)
    echo "##vso[task.setvariable variable=PythonPackagePath;]$ParentDir/$(System.TeamProject)"

  displayName: 'Set Package Path'

- script: |
    echo PythonPackagePath is $(PythonPackagePath)
    
    echo Moving files from $(System.DefaultWorkingDirectory) to $(PythonPackagePath)
    mv $(System.DefaultWorkingDirectory) $(PythonPackagePath)

    echo SymLinking old Working Directory back in case needed
    ln -s $(PythonPackagePath) $(System.DefaultWorkingDirectory)
    ls -l $(System.DefaultWorkingDirectory)/..
  displayName: 'Move Working Directory'

- script: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
  displayName: 'Install dependencies'
  # continueOnError: true

- script: |
    export PYTHONPATH=$(PythonPackagePath)
    echo PYTHONPATH is set to $PYTHONPATH

    cd $(PythonPackagePath)
    echo Working in:
    pwd

    pip install pytest pytest-azurepipelines
    pip install pytest-cov
    pytest --cov=. --cov-report=xml
  displayName: 'pytest'

- task: PublishCodeCoverageResults@1
  inputs:
    codeCoverageTool: Cobertura
    summaryFileLocation: '$(PythonPackagePath)/**/coverage.xml'

我沿着掉进了几个陷阱:

  1. $(VariableName)形式的ADO管道变量在步骤开始时解析,而不是在到达行时解析-因此您需要在使用它之前在 previous step 中设置变量。
  2. bash将在变量中保留一个相对目录引用。所以你不能export ParentDir=..也不能export ParentDir=$(System.DefaultWorkingDirectory)/..在第一种情况下ParentDir总是当前工作目录的父目录,在第二种情况下符号链接将由于循环引用而失败。RegEx ${PWD%/*}获取当前目录的值,并返回最后一个斜杠之前的值。
  3. pytest不喜欢跟随符号链接-所以你不能简单地ln -s path/to/code/s path/to/code/PackageName pytest仍然会认为包被称为 s
    1.设置PYTHONPATH并不是绝对必要的,从正确的目录运行pytest似乎是这个配置中最稳定的选项。
    1.我在获得代码覆盖率以正确发布方面遇到了一些问题。我认为它也不喜欢符号链接-所以不要忘记在相关步骤中更新路径。
    无论测试是否在子文件夹中,这都有效。我的整体结构是:
FooBar
      __init__.py
    ¦
    -- Doomsday
      __init__.py
      Fuel.py
      test_Fuel.py
      ...
    ¦
    -- Utils
          __init__.py
          Maths.py
          ...
        ¦
        --test
              test_Maths1.py
              test_Maths2.py
              ...

其中:

  • FooBar也是我的ADO项目的名称
  • Doomsday的pytest测试位于Doomsday目录中
  • Utils的pytest测试位于子文件夹中
  • 引用的格式为from FooBar.Utils.Maths import prod,这些引用可以正确工作
q35jwt9p

q35jwt9p2#

很确定这与Azure DevOps Pipelines - Python - ModuleNotFoundError despite sys.path.append() or setting PYTHONPATH有关,它说:
在与Azure DevOps支持人员交谈后,我现在知道我的问题是DevOps-Pipelines中的一个bug。

cwdobuhd

cwdobuhd3#

我最近遇到了类似的问题,找到了一个简单的解决方法。该问题至少存在于Windows机器上运行的Azure DevOps代理上。我尚未验证Linux计算机上是否存在此问题。
问题是Windows DevOps代理使用反斜杠i路径作为$(Build.SourcesDirectory)或$(System.DefaultWorkingDirectory),并且反斜杠被视为导入命令中的转义字符,从而导致各种问题。

一个简单的解决方法是将路径中的反斜杠替换为正斜杠:

(In在这个例子中,我导入了_version.py文件,并将__version__参数保存为管道中的变量):

- task: PythonScript@0
  displayName: 'Retrieve software version'
  inputs:
    scriptSource: inline
    script: |
      import sys
      path = r"$(Build.SourcesDirectory)"
      path = path.replace("\\", "/")
      sys.path.append(path)

      from _version import __version__
      print("SW version: ", __version__)
      print(f'##vso[task.setvariable variable=SwVersion]{__version__}')

相关问题