【问题标题】:Python script runs in PyCharm but not Git BashPython 脚本在 PyCharm 中运行,但不在 Git Bash 中
【发布时间】:2018-03-23 02:48:50
【问题描述】:

假设我有一个任意大的模块化 Python 2.7 代码库:

project
↳ docs
↳ etc
↳ package
  ↳ module1
    ↳ submodule1
      ↳ subsubmodule1
        ↳ __init__.py
      ↳ subsubmodule2 (... and so on)
      ↳ __init__.py
    ↳ submodule2
      ↳ subsubmodule1
        ↳ __init__.py
      ↳ subsubmodule2 (... and so on)
      ↳ __init__.py
    ↳ submodule3 (... and so on)
      ↳ __init__.py
  ↳ module2
    ↳ submodule1
      ↳ __init__.py
    ↳ submodule2 (... and so on)
      ↳ __init__.py
    ↳ __init__.py        
  ↳ module3 (... and so on)
    ↳ __init__.py
  ↳ __init__.py
↳ test
  • project 是根文件夹——它是一个 PyCharm 项目,它不是一个模块。
  • project\package 是项目的根 Python 模块。它包含许多子目录,每个子目录都是一个名为moduleN 的Python 模块。
  • 每个project\package\moduleN 模块都包含许多子目录,每个子目录都是一个名为submoduleN 的Python 模块……以此类推。

假设我想要运行一个名为 foo.py 的特定 Python 脚本,它位于 package 下的无数子模块之一中:

# foo.py:

from package.module2.submodule3 import foo
print foo.bar()

当脚本从 PyCharm 运行时,Ctrl+F9:没问题,foo.bar() 打印。

但是当脚本从 Git Bash 终端运行时,从主目录,使用:

python path/to/project/package/module4/submodule6/subsubmobile5/foo.py

抛出以下错误:

ImportError: 没有名为 package.module2.submodule3 的模块


我想知道我需要做什么才能让我的脚本在 Git Bash 上运行,以及为什么 PyCharm 和 Git Bash 之间首先存在差异。和PYTHONPATH有关系吗?


编辑

  • 许多 StackOverflow 的答案建议使用sys.path.append() hacks 的一些迭代。这些建议都不适用于我的情况。
  • 我使用export PYTHONPATH=absolute/path/to/project/package 设置了一个.bashrc 文件,其中package 是我在PyCharm 中的源根目录,但仍然抛出导入错误。相对路径也不起作用。我已经用echo $PYTHONPATH 验证了路径是正确的。 export PYTHONPATH=absolute/path/to/project 同样不起作用。
  • 工作目录似乎无关紧要 - 无论工作目录如何,Git Bash 每次都会失败,而无论工作目录如何,PyCharm 每次都能正常工作。

编辑 2

该问题仍未解决,但可能与在 Git Bash 上未正确设置 PYTHONPATH 有关。当Add Content Roots to PYTHONPATH未勾选时,PyCharm 会抛出与 Git Bash 相同的导入错误。

【问题讨论】:

  • 如果你在 PyCharm 中设置了 'sources root' 变量,这将更新你的 pythonpath 变量。这不会在 gitbash 中自动设置 - 你可以右键单击项目结构中的文件夹并选择'将目录标记为>'以查看它是否被标记为'sources root'。在项目结构中查找设置为蓝色的文件夹图标,然后在程序的入口脚本中,使用 os.path.append('dir') 在 python 路径上设置此目录
  • project 已在 PyCharm 中设置为源根。 PyCharm 有效,我的大问题是 Git Bash。如何在 Git Bash 中“在 python 路径上设置这个目录”?
  • 你有很多设置 python 路径的选项。您可以使用 python 路径更新 .bashrc,您可以更新您的 python 脚本以通过 os.path.append('//') 设置 python 路径,您可以使用 bash 包装器Python 模块在执行 Python 模块之前导出 PYTHONPATH 的脚本
  • 查看this 的答案,了解这个问题的“干净”解决方案
  • @AK47 我使用export PYTHONPATH=path/to/project/package 创建了一个.bashrc 配置文件,其中package 是我在PyCharm 中的根,但我仍然收到导入错误。

标签: python python-2.7 pycharm git-bash


【解决方案1】:

最终,Laurent'sanswers 帮助我解决了这个问题。

我用过:

    import sys
    for p in sys.path:
        print(p)

帮助我确定在 PyCharm 上添加到 PYTHONPATH 的内容与 Git Bash 之间确实存在差异。在 PyCharm 上,/path/to/project/path/to/project/package被添加到 PYTHONPATH。在 Git Bash 上,只添加了一个。

所以我修改了.bashrc 中的export 语句,使其将两条路径都附加到PYTHONPATH;即来自:

export PYTHONPATH="${PYTHONPATH}:absolute/path/to/project/package"

到:

export PYTHONPATH="${PYTHONPATH}:absolute/path/to/project:absolute/path/to/project/package"

然后解决了导入错误。1 同样,当PATHPYTHONPATH 用户环境变量被类似声明时,该脚本在 Windows 命令提示符下工作。

我最好的猜测是,将 PyCharm 中的 Sources Root 设置为项目目录以外的其他内容可能需要对 PYTHONPATH 进行多次添加。

1 在站点注释上:然后我的脚本开始无限期挂起,这已通过别名 Python 解决:alias python="winpty python"

编辑:

Git Bash 在 MinGW64 下运行 - 其中export 语句中的 Windows 路径列表在被 Python 的导入解析处理之前受制于Posix path conversion

所以从技术上讲,export PYTHONPATH="absolute/path/to/project;absolute/path/to/project/package" 应该正确解析为两条路径。

【讨论】:

  • 你的源代码一定有问题。在源代码中搜索(使用递归grep -r import)不以根包开头的导入。您可以将结果放在 GitHub Gist 中并分享。我去看看。
  • @LaurentLAPORTE 最初我的from blah import blah 声明是从项目级别开始的(即from project.package.module1....),但我觉得project. 变得多余,所以我取消了它以支持package.module1.。我真的不认为这是一个问题(除非它是!)。否则,此约定在整个应用程序中是一致的。
  • 根包是package。要解决您的问题,请将所有 project.package.xxx 替换为 package.xxx。你指出错误,干得好!
  • @LaurentLAPORTE 感谢 Laurent - 我应该注意整个项目的约定 package.module1...
【解决方案2】:

注意:如果您的应用程序/库具有第三方依赖项,则下面公开的解决方案将不起作用。为此,您需要一个virtualenv。见我的previous answer

path\to\project 中有以下树结构:

path\to\project
├───docs
├───etc
├───package
│   │   __init__.py
│   ├───module1 [...]
│   ├───module2
│   │   │   __init__.py
│   │   ├───submodule1 [...]
│   │   ├───submodule2 [...]
│   │   └───submodule3
│   │           foo.py
│   │           __init__.py
│   ├───module3 [...]
│   └───module4
│       │   __init__.py
│       └───submodule6
│           │   __init__.py
│           └───subsubmobile5
│                   foo.py
│                   __init__.py
└───tests

这里,package 是您项目的根 Python 包,path\to\project 是您的项目源目录(PyCharm 使用的目录)。

要运行此包中的脚本,例如脚本package/module4/submodule6/subsubmobile5/foo.py,您需要将PYTHONPATH 设置为项目的根目录,即path\to\project

但是,由于您在 Windows 上运行 Git Bash,因此您需要将 Windows 路径转换为有效的 Linux 路径,并使用正斜杠。

一种方法如下:

$ export PYTHONPATH=path/to/project && python path/to/project/package/module4/submodule6/subsubmobile5/foo.py

你甚至可以执行模块package.module4.submodule6.subsubmobile5.foo:

$ export PYTHONPATH=path/to/project && python -m package.module4.submodule6.subsubmobile5.foo

【讨论】:

  • 当我cdproject 目录时,运行python -m package.module4.submodule6.subsubmobile5.foo 会抛出错误/usr/bin/python2.7: Import by filename is not supported.。运行 python -m package.module4.submodule6.subsubmobile5 会引发错误 /usr/bin/python2.7: No module named package.module4.submodule6.subsubmobile5。更改用户环境变量下的 Windows PYTHONPATH 似乎没有影响,因为 Git Bash 似乎没有继承其 PYTHONPATH。我的 Git Bash PYTHONPATH 一直在使用正斜杠。
【解决方案3】:

解决您的问题的正确方法是破解PYTHONPATH,因为如果您的库/应用程序具有第三方依赖项,这将无用。

为了正常工作,PyCharm 使用了两件事:

  • 源根(添加到PYTHONPATH),以及,
  • 项目解释器(即 virtualenv),

要检查这一点,请在 PyCharm 中打开终端视图,然后尝试:

$ python
>>> import sys
>>> for p in sys.path:
...     print(p)
...

正确的方法是使用virtualenv

要在 Windows 上创建 virtualenv,请转到要创建 virtualenv 的目录。 它可以在一个唯一的目录中(就像pew推荐的那样), 或在您的项目目录中(通常在.venv)。

virtualenv -p C:\Python27\python.exe yourvenv

然后,激活您的 virtualenv 并在开发/可编辑模式下安装您的应用程序:

yourvenv\Scripts\activate

cd path\to\project\
pip install -e .

在这里,您已经安装了包含所有依赖项的库/应用程序。 -e 标志表示“可编辑”(与旧的“开发”模式匹配), 请参阅pip 文档。

只要你想运行一个脚本,你可以这样做:

yourvenv\Scripts\activate
python -m package.module4.submodule6.subsubmobile5.foo

在 Windows 上,您也可以这样做:

yourvenv\Scripts\activate
python path\to\project\package\module4\submodule6\subsubmobile5\foo.py

在 Git bash 上,你可以这样做:

source yourvenv/Scripts/activate
python path/to/project/package/module4/submodule6/subsubmobile5/foo.py

如果你想从另一个批次调用你的 Python 脚本,你可以这样做:

yourvenv/Scripts/python.exe -m package.module4.submodule6.subsubmobile5.foo
yourvenv/Scripts/python.exe path/to/project/package/module4/submodule6/subsubmobile5/foo.py

【讨论】:

  • 谢谢,但在我的特殊情况下,pip 是不行的。我目前没有从我的程序中引用任何第三方库,我应该注意我不能使用第三方库来解决这个问题。
猜你喜欢
  • 2017-09-03
  • 2015-12-05
  • 2016-07-23
  • 2015-04-09
  • 2017-09-21
  • 2018-04-17
  • 1970-01-01
  • 2017-04-02
  • 2012-03-25
相关资源
最近更新 更多