尝试导入 Python 文件时可以在 Python 文件中使用破折号吗?

Posted

技术标签:

【中文标题】尝试导入 Python 文件时可以在 Python 文件中使用破折号吗?【英文标题】:Is it ok to use dashes in Python files when trying to import them? 【发布时间】:2010-10-20 04:15:55 【问题描述】:

基本上当我有一个类似的python文件时:

python-code.py

并使用:

import (python-code)

解释器给我语法错误。

关于如何解决它的任何想法? python 文件名中的破折号是非法的吗?

【问题讨论】:

【参考方案1】:

问题在于python-code 不是标识符。解析器将其视为python 减去code。当然,这不会满足您的要求。您将需要使用一个也是有效的 Python 标识符的文件名。尝试将- 替换为下划线。

【讨论】:

+1。从来没想过Python源代码的文件名应该是一个有效的标识符,因为文件名会被用来引用模块对象。【参考方案2】:

您应该查看PEP 8,Python 代码样式指南:

包和模块名称模块应该有简短的全小写名称。如果提高可读性,可以在模块名称中使用下划线。 Python 包也应该有简短的全小写名称,但不鼓励使用下划线。

由于模块名称被映射到文件名,并且一些文件系统不区分大小写并截断长名称,因此选择相当短的模块名称很重要——这在 Unix 上不是问题,但它将代码传输到较旧的 Mac 或 Windows 版本或 DOS 时可能会出现问题。

换句话说:重命名你的文件:)

【讨论】:

问题与样式无关,是语法 错误 如下图,这个名字的文件还是有可能的,所以风格指南非常相关。 当您明确想要阻止导入时,在 Python 目录和文件名中使用连字符会非常有帮助。例如,在(比如说)一个 Django 项目中,您可能有用 Python 编写的脚本,这些脚本不应作为应用程序进行寻址。您可以将它们放在像ops-scripts 这样的文件夹中,并且知道它们不能使用普通的包命名空间方法导入。或者可以将单个脚本命名为 stop-website.py 以获得类似的效果。当然,其中任何一个都可以通过runpy 和其他一些方法导入,但这有助于避免一些常见错误。 重命名模块可能会有问题,尤其是在您依赖其他标准时。就我而言,我在cgi-bin 文件夹中使用python cgi 文件(对它们进行单元测试),这是非常标准的afaik。除非您遇到这种罕见的情况,否则如果您可以控制它,请务必重命名您的模块。 我刚刚发现 PyDev 将允许使用连字符的目录名称,但不会显示该目录中包含的 .py 文件中的类和/或内部变量。【参考方案3】:

您可能可以通过一些__import__ hack 来导入它,但如果您还不知道如何操作,则不应该这样做。 Python 模块名应该是有效的变量名(“标识符”)——这意味着如果你有一个模块 foo_bar,你可以在 Python 中使用它(print foo_bar)。你不能用一个奇怪的名字来这样做(print foo-bar -> 语法错误)。

【讨论】:

【参考方案4】:

在您的代码中要注意的另一件事是导入不是函数。所以import(python-code) 应该是import python-code,正如一些人已经提到的,它被解释为“导入python 减去代码”,而不是你想要的。如果您确实需要导入名称中带有破折号的文件,您可以执行以下操作::

python_code = __import__('python-code')

但是,如上所述,这并不是真正推荐的。如果文件名由您控制,您应该更改它。

【讨论】:

@KevinAudleman 你有使用带连字符文件的导入库的工作示例吗?我试过了,失败了。 @TomHale importlib.import_module('a.b.module-1') 应该可以工作。如果你的 import_module 不起作用,我认为正常的导入也不起作用。【参考方案5】:

TLDR

破折号是非法的,但你不应该使用它们,原因有 3 个:

    您需要特殊的语法来导入带有破折号的文件 没有人希望模块名称带有破折号 这违反了Python Style Guide 的建议

如果您确实需要导入带有破折号的文件名,特殊语法如下:

module_name = __import__('module-name')

好奇我们为什么需要特殊语法?

使用特殊语法的原因是,当您编写 import somename 时,您正在创建一个标识符为 somename 的模块对象(因此您可以稍后将它与 somename.funcname 一起使用)。当然,module-name 不是一个有效的标识符,因此是给出有效标识符的特殊语法。

你不明白为什么 module-name 不是有效的标识符?

别担心——我也没有。这是一个可以帮助您的提示:查看这条 python 行:x=var1-var2。您是否看到赋值右侧的减法或带有破折号的变量名?

附言

我的答案中没有任何原创内容,除了在一个地方包含我认为与所有其他答案中最相关的信息位

【讨论】:

我正在尝试使用此导入带有连字符的 pip 包。 psycopg2_binary = import_module('psycopg2-binary')。错误 => ModuleNotFoundError: No module named 'psycopg2-binary'。但是安装了psycopg2-binary。不知道如何包含它。 可能是路径问题。看chrisyeh96.github.io/2017/08/08/… 1 > "TLDR" 2 > “我的答案中没有任何原创内容,除了在一个地方包含我认为与所有其他答案中最相关的信息” 上面这两个陈述是否一致? :) 没有人希望模块名称带有破折号”。这是真的,但每个人都希望能够重用在另一个文件名有效的文件中定义的类(读取在任何常见的操作系统中都是有效的,包括最常用的操作系统,Windows)。所以问题更多:使用外部文件中定义的类而不使用基于有效标识符而不是有效文件路径的“导入”的解决方案是什么?看来 Python 没有接受等效于“import * from this-valid~filepath”的解决方案,我认为这是一个问题。【参考方案6】:

虽然正确的文件命名是最好的方法,但如果python-code 不受我们控制,使用__import__ 的黑客攻击比复制、重命名或以其他方式弄乱其他作者的代码要好。但是,我试过了,除非我重命名文件并添加 .py 扩展名,否则它不起作用。在查看the doc 以得出如何获取.py 的描述后,我得出了以下结论:

import imp

try:
    python_code_file = open("python-code")
    python_code = imp.load_module('python_code', python_code_file, './python-code', ('.py', 'U', 1))
finally:
    python_code_file.close()

它在第一次运行时创建了一个新文件python-codec

【讨论】:

"虽然正确的文件命名是最好的课程",但正确的文件命名是操作系统的问题,而不是 Python 思维的问题。在文件名中使用破折号对操作系统有效。 Python 定义了什么是 Python 程序中的有效标识符,这是不一样的。【参考方案7】:

在 Python 3 上使用 import_module:

from importlib import import_module
python_code = import_module('python-code')

更一般地说,

import_module('package.subpackage.module')

【讨论】:

以上是关于尝试导入 Python 文件时可以在 Python 文件中使用破折号吗?的主要内容,如果未能解决你的问题,请参考以下文章

Python UDF - 导入/读取外部文件

缺少导入 cv2 - python3.7

导入 CSV 文件时 Python 3 中的 UnicodeDecodeError

Python - Pandas Dataframe 在导入时忽略 \

通过文件路径导入模块时使用 Python 多处理

将python文件导入jupyter笔记本