标签归档:import

从另一个文件导入变量?

问题:从另一个文件导入变量?

如何将变量从一个文件导入到另一个文件?

示例:file1具有变量x1以及x2如何将其传递给file2

如何将所有变量从一个导入到另一个?

How can I import variables from one file to another?

example: file1 has the variables x1 and x2 how to pass them to file2?

How can I import all of the variables from one to another?


回答 0

from file1 import *  

将导入file1中的所有对象和方法

from file1 import *  

will import all objects and methods in file1


回答 1

导入file1内部file2

要从文件1导入所有变量而不泛洪文件2的命名空间,请使用:

import file1

#now use file1.x1, file2.x2, ... to access those variables

要将所有变量从file1导入到file2的命名空间(不推荐):

from file1 import *
#now use x1, x2..

文档

虽然from module import *在模块级别使用是有效的,但通常不是一个好主意。首先,它失去了Python否则具有的重要属性-您可以知道每个顶级名称在您喜欢的编辑器中通过简单的“搜索”功能定义的位置。如果某些模块增加了其他功能或类,将来还会给自己带来麻烦。

Import file1 inside file2:

To import all variables from file1 without flooding file2’s namespace, use:

import file1

#now use file1.x1, file2.x2, ... to access those variables

To import all variables from file1 to file2’s namespace( not recommended):

from file1 import *
#now use x1, x2..

From the docs:

While it is valid to use from module import * at module level it is usually a bad idea. For one, this loses an important property Python otherwise has — you can know where each toplevel name is defined by a simple “search” function in your favourite editor. You also open yourself to trouble in the future, if some module grows additional functions or classes.


回答 2

最好显式导入x1x2

from file1 import x1, x2

这样可以避免file1在中工作时与变量和函数发生不必要的命名空间冲突file2

但是,如果您确实需要,可以导入所有变量:

from file1 import * 

Best to import x1 and x2 explicitly:

from file1 import x1, x2

This allows you to avoid unnecessary namespace conflicts with variables and functions from file1 while working in file2.

But if you really want, you can import all the variables:

from file1 import * 

回答 3

实际上,使用以下命令导入变量并不完全相同:

from file1 import x1
print(x1)

import file1
print(file1.x1)

在导入时,x1和file1.x1的值完全相同,但它们不是相同的变量。例如,在file1中调用一个修改x1的函数,然后尝试从主文件中打印该变量:您将看不到修改后的值。

Actually this is not really the same to import a variable with:

from file1 import x1
print(x1)

and

import file1
print(file1.x1)

Altough at import time x1 and file1.x1 have the same value, they are not the same variables. For instance, call a function in file1 that modifies x1 and then try to print the variable from the main file: you will not see the modified value.


回答 4

马克的回答是正确的。实际上,您可以打印变量的内存地址,print(hex(id(libvar))并且可以看到地址是不同的。

# mylib.py
libvar = None
def lib_method():
    global libvar
    print(hex(id(libvar)))

# myapp.py
from mylib import libvar, lib_method
import mylib

lib_method()
print(hex(id(libvar)))
print(hex(id(mylib.libvar)))

Marc response is correct. Actually, you can print the memory address for the variables print(hex(id(libvar)) and you can see the addresses are different.

# mylib.py
libvar = None
def lib_method():
    global libvar
    print(hex(id(libvar)))

# myapp.py
from mylib import libvar, lib_method
import mylib

lib_method()
print(hex(id(libvar)))
print(hex(id(mylib.libvar)))

回答 5

script1.py

title="Hello world"

script2.py是我们使用script1变量的地方

方法1:

import script1
print(script1.title)

方法2:

from script1 import title
print(title)

script1.py

title="Hello world"

script2.py is where we using script1 variable

Method 1:

import script1
print(script1.title)

Method 2:

from script1 import title
print(title)

回答 6

Python您可以访问的其他文件的内容像,就好像它们
是某种库,比起像Java或任何OOP语言基础等语言,这是真的很酷;

这使得可以访问文件的内容或将其导入以对其进行处理或对其进行任何处理;这就是为什么Python高度首选数据科学和机器学习等语言的主要原因;

这是 project structure

我从.env file哪里访问API links秘密密钥和秘密密钥所在的位置。

总体结构:

from <File-Name> import *

In Python you can access the contents of other files like as if they
are some kind of a library, compared to other languages like java or any oop base languages , This is really cool ;

This makes accessing the contents of the file or import it to to process it or to do anything with it ; And that is the Main reason why Python is highly preferred Language for Data Science and Machine Learning etc. ;

And this is the picture of project structure

Where I am accessing variables from .env file where the API links and Secret keys reside .

General Structure:

from <File-Name> import *

回答 7

first.py:

a=5

second.py:

import first
print(first.a)

结果将是5。

first.py:

a=5

second.py:

import first
print(first.a)

The result will be 5.


存在相同名称的模块时从内置库导入

问题:存在相同名称的模块时从内置库导入

情况:-我的project_folder中有一个名为Calendar的模块-我想使用Python库中的内置Calendar类-当我从日历导入Calendar中使用时,它抱怨,因为它试图从我的模块中加载。

我进行了几次搜索,但似乎找不到解决我问题的方法。

有任何想法而不必重命名我的模块吗?

Situation: – There is a module in my project_folder called calendar – I would like to use the built-in Calendar class from the Python libraries – When I use from calendar import Calendar it complains because it’s trying to load from my module.

I’ve done a few searches and I can’t seem to find a solution to my problem.

Any ideas without having to rename my module?


回答 0

公认的解决方案包含一种现已弃用的方法。

这里的importlib文档为直接从python> = 3.5的文件路径中加载模块的更合适方法提供了一个很好的示例:

import importlib.util
import sys

# For illustrative purposes.
import tokenize
file_path = tokenize.__file__  # returns "/path/to/tokenize.py"
module_name = tokenize.__name__  # returns "tokenize"

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)

因此,您可以从路径加载任何.py文件,并将模块名称设置为所需的名称。所以只要调整module_name为您希望模块在导入时使用的任何自定义名称即可。

要加载程序包而不是单个文件,file_path应为程序包根目录的路径__init__.py

The accepted solution contains a now-deprecated approach.

The importlib documentation here gives a good example of the more appropriate way to load a module directly from a file path for python >= 3.5:

import importlib.util
import sys

# For illustrative purposes.
import tokenize
file_path = tokenize.__file__  # returns "/path/to/tokenize.py"
module_name = tokenize.__name__  # returns "tokenize"

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)

So, you can load any .py file from a path and set the module name to be whatever you want. So just adjust the module_name to be whatever custom name you’d like the module to have upon importing.

To load a package instead of a single file, file_path should be the path to the package’s root __init__.py


回答 1

无需更改模块名称。相反,您可以使用absolute_import更改导入行为。例如,以stem / socket.py导入套接字模块,如下所示:

from __future__ import absolute_import
import socket

这仅适用于Python 2.5及更高版本;这是Python 3.0及更高版本中的默认行为。Pylint会抱怨该代码,但这是完全有效的。

Changing the name of your module is not necessary. Rather, you can use absolute_import to change the importing behavior. For example with stem/socket.py I import the socket module as follows:

from __future__ import absolute_import
import socket

This only works with Python 2.5 and above; it’s enabling behavior that is the default in Python 3.0 and higher. Pylint will complain about the code but it’s perfectly valid.


回答 2

实际上,解决这个问题很容易,但是实现总是有些脆弱,因为它取决于python导入机制的内部,并且在将来的版本中可能会发生变化。

(以下代码显示了如何加载本地和非本地模块以及它们如何共存)

def import_non_local(name, custom_name=None):
    import imp, sys

    custom_name = custom_name or name

    f, pathname, desc = imp.find_module(name, sys.path[1:])
    module = imp.load_module(custom_name, f, pathname, desc)
    f.close()

    return module

# Import non-local module, use a custom name to differentiate it from local
# This name is only used internally for identifying the module. We decide
# the name in the local scope by assigning it to the variable calendar.
calendar = import_non_local('calendar','std_calendar')

# import local module normally, as calendar_local
import calendar as calendar_local

print calendar.Calendar
print calendar_local

如果可能的话,最好的解决方案是避免使用与标准库或内置模块名称相同的名称来命名模块。

Actually, solving this is rather easy, but the implementation will always be a bit fragile, because it depends python import mechanism’s internals and they are subject to change in future versions.

(the following code shows how to load both local and non-local modules and how they may coexist)

def import_non_local(name, custom_name=None):
    import imp, sys

    custom_name = custom_name or name

    f, pathname, desc = imp.find_module(name, sys.path[1:])
    module = imp.load_module(custom_name, f, pathname, desc)
    f.close()

    return module

# Import non-local module, use a custom name to differentiate it from local
# This name is only used internally for identifying the module. We decide
# the name in the local scope by assigning it to the variable calendar.
calendar = import_non_local('calendar','std_calendar')

# import local module normally, as calendar_local
import calendar as calendar_local

print calendar.Calendar
print calendar_local

The best solution, if possible, is to avoid naming your modules with the same name as standard-library or built-in module names.


回答 3

解决此问题的唯一方法是自己劫持内部进口设备。这并不容易,而且充满了危险。您应不惜一切代价避免使用圣杯形的信标,因为其危险性很高。

重命名您的模块。

如果您想学习如何劫持内部导入机制,可以在这里找到如何执行此操作的方法:

有时有充分的理由陷入这种危险。您给出的原因不在其中。重命名您的模块。

如果您选择危险的路径,将会遇到的一个问题是,当您加载模块时,它会以“正式名称”结尾,这样Python就可以避免再次解析该模块的内容。可以在中找到模块的“正式名称”到模块对象本身的映射sys.modules

这意味着,如果您 import calendar在某个地方,那么导入的任何模块都将被视为具有官方名称的模块,calendar并且所有其他尝试到import calendar任何其他地方的模块(包括在主Python库的其他代码中)都将获得该日历。

可能可以使用 Python 2.x中 imputil模块模块导致从某些路径加载的模块以不同于sys.modulesfirst或类似的方式查找要导入的模块。但这是一件非常繁琐的事情,而且无论如何在Python 3.x中都无法使用。

您可以做的一件非常丑陋和可怕的事情,不涉及挂钩导入机制。您可能不应该这样做,但是可能会起作用。它将您的calendar模块变成系统日历模块和日历模块的混合体。感谢Boaz Yaniv提供的功能框架。将其放在calendar.py文件的开头:

import sys

def copy_in_standard_module_symbols(name, local_module):
    import imp

    for i in range(0, 100):
        random_name = 'random_name_%d' % (i,)
        if random_name not in sys.modules:
            break
        else:
            random_name = None
    if random_name is None:
        raise RuntimeError("Couldn't manufacture an unused module name.")
    f, pathname, desc = imp.find_module(name, sys.path[1:])
    module = imp.load_module(random_name, f, pathname, desc)
    f.close()
    del sys.modules[random_name]
    for key in module.__dict__:
        if not hasattr(local_module, key):
            setattr(local_module, key, getattr(module, key))

copy_in_standard_module_symbols('calendar', sys.modules[copy_in_standard_module_symbols.__module__])

The only way to solve this problem is to hijack the internal import machinery yourself. This is not easy, and fraught with peril. You should avoid the grail shaped beacon at all costs because the peril is too perilous.

Rename your module instead.

If you want to learn how to hijack the internal import machinery, here is where you would go about finding out how to do this:

There are sometimes good reasons to get into this peril. The reason you give is not among them. Rename your module.

If you take the perilous path, one problem you will encounter is that when you load a module it ends up with an ‘official name’ so that Python can avoid ever having to parse the contents of that module ever again. A mapping of the ‘official name’ of a module to the module object itself can be found in sys.modules.

This means that if you import calendar in one place, whatever module is imported will be thought of as the module with the official name calendar and all other attempts to import calendar anywhere else, including in other code that’s part of the main Python library, will get that calendar.

It might be possible to design a customer importer using the imputil module in Python 2.x that caused modules loaded from certain paths to look up the modules they were importing in something other than sys.modules first or something like that. But that’s an extremely hairy thing to be doing, and it won’t work in Python 3.x anyway.

There is an extremely ugly and horrible thing you can do that does not involve hooking the import mechanism. This is something you should probably not do, but it will likely work. It turns your calendar module into a hybrid of the system calendar module and your calendar module. Thanks to Boaz Yaniv for the skeleton of the function I use. Put this at the beginning of your calendar.py file:

import sys

def copy_in_standard_module_symbols(name, local_module):
    import imp

    for i in range(0, 100):
        random_name = 'random_name_%d' % (i,)
        if random_name not in sys.modules:
            break
        else:
            random_name = None
    if random_name is None:
        raise RuntimeError("Couldn't manufacture an unused module name.")
    f, pathname, desc = imp.find_module(name, sys.path[1:])
    module = imp.load_module(random_name, f, pathname, desc)
    f.close()
    del sys.modules[random_name]
    for key in module.__dict__:
        if not hasattr(local_module, key):
            setattr(local_module, key, getattr(module, key))

copy_in_standard_module_symbols('calendar', sys.modules[copy_in_standard_module_symbols.__module__])

回答 4

我想提供我的版本,该版本是Boaz Yaniv和Omnifarious解决方案的结合。它将导入模块的系统版本,与先前的答案有两个主要区别:

  • 支持“点”表示法,例如。包模块
  • 是系统模块上import语句的直接替代品,这意味着您只需要替换该行,并且如果已经对模块进行了调用,它们将照常工作

将其放在可访问的位置,以便您可以调用它(我的__init__.py文件中有我的名称):

class SysModule(object):
    pass

def import_non_local(name, local_module=None, path=None, full_name=None, accessor=SysModule()):
    import imp, sys, os

    path = path or sys.path[1:]
    if isinstance(path, basestring):
        path = [path]

    if '.' in name:
        package_name = name.split('.')[0]
        f, pathname, desc = imp.find_module(package_name, path)
        if pathname not in __path__:
            __path__.insert(0, pathname)
        imp.load_module(package_name, f, pathname, desc)
        v = import_non_local('.'.join(name.split('.')[1:]), None, pathname, name, SysModule())
        setattr(accessor, package_name, v)
        if local_module:
            for key in accessor.__dict__.keys():
                setattr(local_module, key, getattr(accessor, key))
        return accessor
    try:
        f, pathname, desc = imp.find_module(name, path)
        if pathname not in __path__:
            __path__.insert(0, pathname)
        module = imp.load_module(name, f, pathname, desc)
        setattr(accessor, name, module)
        if local_module:
            for key in accessor.__dict__.keys():
                setattr(local_module, key, getattr(accessor, key))
            return module
        return accessor
    finally:
        try:
            if f:
                f.close()
        except:
            pass

我想导入mysql.connection,但我已经有一个本地软件包mysql(官方mysql实用程序)。因此,要从系统mysql包中获取连接器,我将其替换为:

import mysql.connector

有了这个:

import sys
from mysql.utilities import import_non_local         # where I put the above function (mysql/utilities/__init__.py)
import_non_local('mysql.connector', sys.modules[__name__])

结果

# This unmodified line further down in the file now works just fine because mysql.connector has actually become part of the namespace
self.db_conn = mysql.connector.connect(**parameters)

I’d like to offer my version, which is a combination of Boaz Yaniv’s and Omnifarious’s solution. It will import the system version of a module, with two main differences from the previous answers:

  • Supports the ‘dot’ notation, eg. package.module
  • Is a drop-in replacement for the import statement on system modules, meaning you just have to replace that one line and if there are already calls being made to the module they will work as-is

Put this somewhere accessible so you can call it (I have mine in my __init__.py file):

class SysModule(object):
    pass

def import_non_local(name, local_module=None, path=None, full_name=None, accessor=SysModule()):
    import imp, sys, os

    path = path or sys.path[1:]
    if isinstance(path, basestring):
        path = [path]

    if '.' in name:
        package_name = name.split('.')[0]
        f, pathname, desc = imp.find_module(package_name, path)
        if pathname not in __path__:
            __path__.insert(0, pathname)
        imp.load_module(package_name, f, pathname, desc)
        v = import_non_local('.'.join(name.split('.')[1:]), None, pathname, name, SysModule())
        setattr(accessor, package_name, v)
        if local_module:
            for key in accessor.__dict__.keys():
                setattr(local_module, key, getattr(accessor, key))
        return accessor
    try:
        f, pathname, desc = imp.find_module(name, path)
        if pathname not in __path__:
            __path__.insert(0, pathname)
        module = imp.load_module(name, f, pathname, desc)
        setattr(accessor, name, module)
        if local_module:
            for key in accessor.__dict__.keys():
                setattr(local_module, key, getattr(accessor, key))
            return module
        return accessor
    finally:
        try:
            if f:
                f.close()
        except:
            pass

Example

I wanted to import mysql.connection, but I had a local package already called mysql (the official mysql utilities). So to get the connector from the system mysql package, I replaced this:

import mysql.connector

With this:

import sys
from mysql.utilities import import_non_local         # where I put the above function (mysql/utilities/__init__.py)
import_non_local('mysql.connector', sys.modules[__name__])

Result

# This unmodified line further down in the file now works just fine because mysql.connector has actually become part of the namespace
self.db_conn = mysql.connector.connect(**parameters)

回答 5

更改导入路径:

import sys
save_path = sys.path[:]
sys.path.remove('')
import calendar
sys.path = save_path

Change the import path:

import sys
save_path = sys.path[:]
sys.path.remove('')
import calendar
sys.path = save_path

pytest无法导入模块,而python可以

问题:pytest无法导入模块,而python可以

我正在使用Python开发包。我使用virtualenv。我在virtualenv的.pth路径中将模块的根目录设置为路径,以便在开发代码并进行测试时可以导入软件包的模块(问题1:这是一个好方法吗?)。这工作正常(这是一个示例,这是我想要的行为):

(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ python
Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from rc import ns
>>> exit()
(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ python tests/test_ns.py 
issued command: echo hello
command output: hello

但是,如果我尝试使用PyTest,则会收到一些导入错误消息:

(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ pytest
=========================================== test session starts ============================================
platform linux2 -- Python 2.7.12, pytest-3.0.5, py-1.4.31, pluggy-0.4.0
rootdir: /home/zz/Desktop/GitFolders/rc, inifile: 
collected 0 items / 1 errors 

================================================== ERRORS ==================================================
________________________________ ERROR collecting tests/test_ns.py ________________________________
ImportError while importing test module '/home/zz/Desktop/GitFolders/rc/tests/test_ns.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_ns.py:2: in <module>
    from rc import ns
E   ImportError: cannot import name ns
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================= 1 error in 0.09 seconds ==========================================
(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ which pytest
/home/zz/Desktop/VirtualEnvs/VEnvTestRc/bin/pytest

我有点疑惑,它看起来像是一个导入错误,但是Python很好,所以为什么PyTest特有问题?对原因/补救措施有什么建议(问题2)?我用谷歌搜索并堆栈溢出了PyTest的“ ImportError:无法导入”错误,但是我得到的结果与缺少python路径有关,并且对此有补救措施,这似乎不是这里的问题。有什么建议?

I am working on a package in Python. I use virtualenv. I set the path to the root of the module in a .pth path in my virtualenv, so that I can import modules of the package while developing the code and do testing (Question 1: is it a good way to do?). This works fine (here is an example, this is the behavior I want):

(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ python
Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from rc import ns
>>> exit()
(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ python tests/test_ns.py 
issued command: echo hello
command output: hello

However, if I try to use PyTest, I get some import error messages:

(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ pytest
=========================================== test session starts ============================================
platform linux2 -- Python 2.7.12, pytest-3.0.5, py-1.4.31, pluggy-0.4.0
rootdir: /home/zz/Desktop/GitFolders/rc, inifile: 
collected 0 items / 1 errors 

================================================== ERRORS ==================================================
________________________________ ERROR collecting tests/test_ns.py ________________________________
ImportError while importing test module '/home/zz/Desktop/GitFolders/rc/tests/test_ns.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_ns.py:2: in <module>
    from rc import ns
E   ImportError: cannot import name ns
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================= 1 error in 0.09 seconds ==========================================
(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ which pytest
/home/zz/Desktop/VirtualEnvs/VEnvTestRc/bin/pytest

I am a bit puzzled, it looks like this indicates an import error, but Python does it fine so why is there a problem specifically with PyTest? Any suggestion to the reason / remedy (Question 2)? I googled and stack-overflowed the ‘ImportError: cannot import’ error for PyTest, but the hits I got were related to missing python path and remedy to this, which does not seem to be the problem here. Any suggestions?


回答 0

找到了答案:

__init__.py如果计划使用pytest,请勿将文件放在包含TESTS的文件夹中。我有一个这样的文件,删除它可以解决问题。

这实际上是在pytest“ ImportError:没有名为YadaYadaYada的模块”PATH问题的第二个答案的注释中掩埋的,所以我没有看到它,希望它在这里能够引起更多的关注。

Found the answer:

DO NOT put a __init__.py file in a folder containing TESTS if you plan on using pytest. I had one such file, deleting it solved the problem.

This was actually buried in the comments to the second answer of PATH issue with pytest ‘ImportError: No module named YadaYadaYada’ so I did not see it, hope it gets more visibility here.


回答 1

我不能说我理解为什么会这样,但是我遇到了同样的问题,如果运行,测试也可以正常工作python -m pytest

我在virtualenv中,pytest也可以在全球范围内使用:

(proj)tom@neon ~/dev/proj$ type -a python
python is /home/tom/.virtualenvs/proj/bin/python
python is /usr/bin/python

(proj)tom@neon ~/dev/proj$ python -V
Python 3.5.2

(proj)tom@neon ~/dev/proj$ type -a pytest
pytest is /home/tom/.virtualenvs/proj/bin/pytest
pytest is /usr/bin/pytest

(proj)tom@neon ~/dev/proj$ pytest --version
This is pytest version 3.5.0, imported from /home/tom/.virtualenvs/proj/lib/python3.5/site-packages/pytest.py

I can’t say I understand why this works, but I had the same problem and the tests work fine if I run python -m pytest.

I’m in a virtualenv, with pytest also available globally:

(proj)tom@neon ~/dev/proj$ type -a python
python is /home/tom/.virtualenvs/proj/bin/python
python is /usr/bin/python

(proj)tom@neon ~/dev/proj$ python -V
Python 3.5.2

(proj)tom@neon ~/dev/proj$ type -a pytest
pytest is /home/tom/.virtualenvs/proj/bin/pytest
pytest is /usr/bin/pytest

(proj)tom@neon ~/dev/proj$ pytest --version
This is pytest version 3.5.0, imported from /home/tom/.virtualenvs/proj/lib/python3.5/site-packages/pytest.py

回答 2

我只是通过删除项目根目录中的__init__.py来解决此问题:

.
├── __init__.py <--- removed
├── models
   ├── __init__.py
   ├── address.py
   ├── appointment.py
   └── client.py
├── requirements.txt
├── setup.cfg
├── tests
   ├── __init__.py
   ├── models
      ├── __init__.py
      ├── appointment_test.py
      └── client_test.py
   └── other_test.py
└── script.py

I just solved this by removing the __init__.py in my project root:

.
├── __init__.py <--- removed
├── models
│   ├── __init__.py
│   ├── address.py
│   ├── appointment.py
│   └── client.py
├── requirements.txt
├── setup.cfg
├── tests
│   ├── __init__.py
│   ├── models
│   │   ├── __init__.py
│   │   ├── appointment_test.py
│   │   └── client_test.py
│   └── other_test.py
└── script.py

回答 3

我遇到了同样的问题,但是由于上述原因之外的另一个原因:

我在全局安装了py.test,而软件包则安装在虚拟环境中。

解决方案是pytest在虚拟环境中安装。(如果您的shell像Bash一样哈希可执行文件,请使用hash -r,或使用的完整路径py.test

I had the same problem but for another reason than the ones mentioned:

I had py.test installed globally, while the packages were installed in a virtual environment.

The solution was to install pytest in the virtual environment. (In case your shell hashes executables, as Bash does, use hash -r, or use the full path to py.test)


回答 4

如果您有一个tests.py文件和一个带有的测试文件夹,则会发生此问题tests/__init__.py

在收集过程中,pytest会找到文件夹,但是当尝试从文件夹中导入测试文件时,tests.py文件会导致导入问题。

要解决此问题,只需删除tests.py文件,然后将所有测试放在tests/文件夹中即可。

对于您的特定情况,修复将精确地是:

  • 删除文件 /home/zz/Desktop/GitFolders/rc/tests.py
  • 确保/home/zz/Desktop/GitFolders/rc/tests/__init__.py存在

This problem will happen if you have a tests.py file and a tests folder with tests/__init__.py.

During the collection pytest finds the folder, but when it tries to import the test files from the folder, tests.py file will cause the import problem.

To fix simply remove the tests.py file and put all your tests inside the tests/ folder.

For your specific case the fix will be precisely:

  • Remove the file /home/zz/Desktop/GitFolders/rc/tests.py
  • Make sure /home/zz/Desktop/GitFolders/rc/tests/__init__.py is present

回答 5

我有一个类似的问题,完全相同的错误,但原因不同。我正在运行测试代码,但是使用的是模块的旧版本。在我的代码的先前版本中,一个类存在,而另一个不存在。更新代码后,我应该运行以下命令进行安装。

sudo pip install ./ --upgrade

安装更新的模块后,运行pytest会产生正确的结果(因为我使用的是正确的代码库)。

I had a similar issue, exact same error, but different cause. I was running the test code just fine, but against an old version of the module. In the previous version of my code one class existed, while the other did not. After updating my code, I should have run the following to install it.

sudo pip install ./ --upgrade

Upon installing the updated module running pytest produced the correct results (because i was using the correct code base).


回答 6

在我的情况下,发生导入错误是因为程序包指向另一个具有相同名称的程序包/目录,并且其路径在我实际想要的文件夹上方一层。我认为这也解释了为什么有些人需要删除_ init _.py而另一些人需要重新添加。

我只是在控制台和脚本中print(the_root_package.__path__)(在之后import the_root_package)放置以比较差异pythonpytest

底线:执行此操作时python,导入的包可能与运行时的包不同pytest

In my case, the import error occurred because the package is pointing to another package/directory with the same name and its path is one level above the folder I actually wanted. I think this also explains why some people need to remove _ init _.py while others need to add back.

I just put print(the_root_package.__path__) (after import the_root_package) in both python console and pytest scripts to compare the difference

BOTTOM LINE: When you do python, the package you import may be different from the package when you run pytest.


回答 7

将软件包安装到您的虚拟环境中。
然后启动一个新的Shell并再次获取您的虚拟环境。

Install the packages into Your virtual environment.
Then start a new shell and source Your virtual environment again.


回答 8

上面的答案对我不起作用。我只是通过将未找到的模块的绝对路径附加到(您的测试模块)的sys.path顶部来解决它test_xxx.py,例如:

import sys
sys.path.append('path')

The answer above not work for me. I just solved it by appending the absolute path of the module which not found to the sys.path at top of the test_xxx.py (your test module), like:

import sys
sys.path.append('path')

回答 9

如果它与最初在python 2.7中开发,现在迁移到python 3.x的python代码有关,则该问题可能与导入问题有关。

例如,从base同一目录中的文件导入对象时,它将在python 2.x中工作:

from base import MyClass

在python 3.x中,您应该替换为base完整路径,否则.base 将导致上述问题。所以尝试:

from .base import MyClass

If it is related to python code that was originally developed in python 2.7 and now migrated into python 3.x than the problem is probably related to an import issue.

e.g. when importing an object from a file: base that is located in the same directory this will work in python 2.x:

from base import MyClass

in python 3.x you should replace with base full path or .base not doing so will cause the above problem. so try:

from .base import MyClass

回答 10

我今天遇到了这个问题,并通过python -m pytest从项目目录的根目录进行调用来解决了。

pytest从同一位置拨打电话仍然会引起问题。

我的项目目录组织为:

api/
 - server/
  - tests/
      - test_routes.py
  - routes/
      - routes.py
 - app.py

该模块routes以我的test_routes.py身份导入:from server.routes.routes import Routes

希望有帮助!

I was experiencing this issue today and solved it by calling python -m pytest from the root of my project directory.

Calling pytest from the same location still caused issues.

My Project dir is organized as:

api/
 - server/
  - tests/
      - test_routes.py
  - routes/
      - routes.py
 - app.py

The module routes was imported in my test_routes.py as: from server.routes.routes import Routes

Hope that helps!


回答 11

另一个特殊情况:

我在使用毒药时遇到了问题。因此,我的程序运行良好,但是通过Tox进行的单元测试一直在抱怨。安装软件包(程序需要)之后,您需要另外在tox.ini中指定单元测试中使用的软件包。

[testenv]
deps =
    package1
    package2 
...

Another special case:

I had the problem using tox. So my program ran fine, but unittests via tox kept complaining. After installing packages (needed for the program) you need to additionally specify the packages used in the unittests in the tox.ini

[testenv]
deps =
    package1
    package2 
...

回答 12

我正在使用VSCode来获得它。我有一个conda环境。我不认为VScode python扩展可以看到我所做的更新。

python c:\Users\brig\.vscode\extensions\ms-python.python-2019.9.34911\pythonFiles\testing_tools\run_adapter.py discover pytest -- -s --cache-clear test
Test Discovery failed:

我必须跑步 pip install ./ --upgrade

I was getting this using VSCode. I have a conda environment. I don’t think the VScode python extension could see the updates I was making.

python c:\Users\brig\.vscode\extensions\ms-python.python-2019.9.34911\pythonFiles\testing_tools\run_adapter.py discover pytest -- -s --cache-clear test
Test Discovery failed:

I had to run pip install ./ --upgrade


回答 13

编辑您的conftest.py并添加以下代码行:

import os, sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(file), '..')))

如果尝试通过终端运行测试用例,请使用以下示例:

python -m pytest test_some_step_file_steps.py --html=HTML_step_file_output.html --self-contained-html

Edit your conftest.py and add following lines of code:

import os, sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(file), '..')))

And if trying to run the test case through terminal, use following ex:

python -m pytest test_some_step_file_steps.py --html=HTML_step_file_output.html --self-contained-html

回答 14

Python的导入系统又获得了一次巨大的胜利。我认为,没有达成共识的原因是,有效的方法可能取决于您的环境以及在其上使用的工具。

我正在VS Code中使用它,它是在conda环境下Windows的Python 3.8中的测试资源管理器中使用的。

我要工作的设置是:

mypkg/
    __init__.py
    app.py
    view.py
tests/
    test_app.py
    test_view.py

在这种设置下,智能感知将起作用,测试发现也将起作用。

请注意,我最初试图以下,推荐这里

src/
    mypkg/
        __init__.py
        app.py
        view.py
tests/
    test_app.py
    test_view.py

我找不到从VS Code上src使它起作用的方法,因为该文件夹使导入系统无所适从。我可以想象有一种方法可以从命令行运行它。作为一种相对较新的Python编程转换,它带给我怀旧的使用COM的感觉,但是却没有那么有趣。

Yet another massive win for Python’s import system. I think the reason there is no consensus is that what works probably depends on your environment and the tools you are using on top of it.

I’m using this from VS Code, in the test explorer under Windows in a conda environment, Python 3.8.

The setup I have got to work is:

mypkg/
    __init__.py
    app.py
    view.py
tests/
    test_app.py
    test_view.py

Under this setup intellisense works and so does test discovery.

Note that I originally tried the following, as recommended here.

src/
    mypkg/
        __init__.py
        app.py
        view.py
tests/
    test_app.py
    test_view.py

I could find no way of getting this to work from VS Code because the src folder just blew the mind of the import system. I can imagine there is a way of getting this to work from the command line. As a relatively new convert to Python programming it gives me a nostalgic feeling of working with COM, but being slightly less fun.


回答 15

如果不使用虚拟环境,我为此付出的2美分:pytest会偶然失败。有时它会工作,有时则不会。

因此,解决方案是:

  • 用pip卸载删除pytest
  • 创建您的venv
  • 激活你的venv
  • pip以可编辑模式安装项目路径,因此pytest会将其视为模块(否则,pytest将找不到您的内部导入)。您将需要一个setup.py文件
  • 安装您的软件包,包括pytest
  • 最后,运行测试

使用Windows PowerShell的代码:

pip uninstall pytest
python.exe -m venv my_env
.\my_env\Scripts\activate
(my_env) pip install -e .
(my_env) pip install pytest pytest-html pandas numpy

然后最后

(my_env) pytest --html="my_testing_report.html"

用于pip install -e的setup.py示例:

import setuptools

setuptools.setup(
    name='my_package',
    version='devel',
    author='erickfis',
    author_email='erickfis@gmail.com',
    description='My package',
    long_description='My gooood package',
    packages=setuptools.find_packages(),
    classifiers=[
        'Programming Language :: Python :: 3',
        'Operating System :: OS Independent',
    ],
    include_package_data=True
)

My 2 cents on this: pytest will fail at chance if you are not using virtual environments. Sometimes it will just work, sometimes not.

Therefore, the solution is:

  • remove pytest with pip uninstall
  • create your venv
  • activate your venv
  • pip install your project path in editable mode, so it will be treated by pytest as a module (otherwise, pytest wont find your internal imports). You will need a setup.py file for that
  • install your packages, including pytest
  • finally, run your tests

The code, using windows PowerShell:

pip uninstall pytest
python.exe -m venv my_env
.\my_env\Scripts\activate
(my_env) pip install -e .
(my_env) pip install pytest pytest-html pandas numpy

Then finally

(my_env) pytest --html="my_testing_report.html"

An example of setup.py, for pip install -e:

import setuptools

setuptools.setup(
    name='my_package',
    version='devel',
    author='erickfis',
    author_email='erickfis@gmail.com',
    description='My package',
    long_description='My gooood package',
    packages=setuptools.find_packages(),
    classifiers=[
        'Programming Language :: Python :: 3',
        'Operating System :: OS Independent',
    ],
    include_package_data=True
)

回答 16

我不同意这些帖子,说您必须删除所有__init__.py文件。您必须要做的是更改sys.path

sys.path正常运行代码的情况下,在您进行打印的地方进行实验。然后sys.path在通过pytest运行代码的同时进行打印。我认为您会发现这两条路径之间存在差异,因此pytest为什么会中断。

要解决此问题,请将第一个实验的路径插入第二个实验的第0个索引。

我们'/usr/exampleUser/Documents/foo'是第一个元素print(sys.path)的实验1。

以下是应该解决您问题的代码:

import sys sys.path[0] = '/usr/exampleUser/Documents/foo'

在实际导入语句之前,将此内容放在文件顶部。

资料来源:我本人正在处理,上述过程解决了它。

I disagree with the posts saying that you must remove any __init__.py files. What you must instead do is alter the sys.path.

Run an experiment where you print sys.path when running the code normally. Then print sys.path while running the code via pytest. I think you will find that there is a difference between these two paths, hence why pytest breaks.

To fix this, insert the path from the first experiment at the 0th index of the second.

Let '/usr/exampleUser/Documents/foo' be the first element of print(sys.path) for experiment 1.

Below is code that should fix your issue:

import sys sys.path[0] = '/usr/exampleUser/Documents/foo'

Put this at the top of your file, before your actual import statement.

Source: I was dealing with this myself and the above process solved it.


回答 17

一切都保持相同,只是增加了在根文件夹中的空白测试文件..解决它

这是调查结果,这个问题确实困扰了我一段时间。我的文件夹结构是

mathapp/
    - server.py  
    - configuration.py 
    - __init__.py 
    - static/ 
       - home.html  
tests/            
    - functional 
       - test_errors.py 
    - unit  
       - test_add.py

pytest会抱怨ModuleNotFoundError并给出提示-确保您的测试模块/软件包具有有效的Python名称。

我在与mathsapp和tests目录相同的级别引入了模拟测试文件。该文件不包含任何内容。现在pytest不会抱怨。

没有文件的结果

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 1 item / 1 error

=================================== ERRORS ====================================
_______________ ERROR collecting tests/functional/test_func.py ________________
ImportError while importing test module 'C:\mainak\workspace\0github\python-rest-app-cont\tests\functional\test_func.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests\functional\test_func.py:4: in <module>
    from mathapp.service import sum
E   ModuleNotFoundError: No module named 'mathapp'
=========================== short test summary info ===========================
ERROR tests/functional/test_func.py
!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
============================== 1 error in 0.24s ===============================

结果与文件

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 2 items

tests\functional\test_func.py .                                          [ 50%]
tests\unit\test_unit.py .                                                [100%]

============================== 2 passed in 0.11s ==============================

Kept everything same and just added a blank test file at the root folder .. Solved it

Here are the findings, this problem really bugged me for a while. My folder structure was

mathapp/
    - server.py  
    - configuration.py 
    - __init__.py 
    - static/ 
       - home.html  
tests/            
    - functional 
       - test_errors.py 
    - unit  
       - test_add.py

and pytest would complain with the ModuleNotFoundError and gives the HINT – make sure your test modules/packages have valid Python names.

I introduced a mock test file at the same level as mathsapp and tests directory. The file contained nothing. Now pytest does not complain.

Result without the file

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 1 item / 1 error

=================================== ERRORS ====================================
_______________ ERROR collecting tests/functional/test_func.py ________________
ImportError while importing test module 'C:\mainak\workspace\0github\python-rest-app-cont\tests\functional\test_func.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests\functional\test_func.py:4: in <module>
    from mathapp.service import sum
E   ModuleNotFoundError: No module named 'mathapp'
=========================== short test summary info ===========================
ERROR tests/functional/test_func.py
!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
============================== 1 error in 0.24s ===============================

Results with the file

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 2 items

tests\functional\test_func.py .                                          [ 50%]
tests\unit\test_unit.py .                                                [100%]

============================== 2 passed in 0.11s ==============================

回答 18

我通过PYTHONPATH为运行测试的特定配置设置环境变量解决了我的问题。

在PyCharm上查看测试文件时:

  1. Ctrl+ Shift+A
  2. 类型 Edit Configurations
  3. PYTHONPATH在环境>环境变量下设置。

I solved my problem by setting the PYTHONPATH in Environment Variables for the specific configuration I’m running my tests with.

While you’re viewing the test file on PyCharm:

  1. Ctrl+Shift+A
  2. Type Edit Configurations
  3. Set your PYTHONPATH under Environment > Environment variables.

回答 19

只需将一个空conftest.py文件放在项目根目录中,因为当pytest发现conftest.py时,它将修改sys.path以便可以从conftest模块中导入内容。常规目录结构可以是:

Root
├── conftest.py
├── module1
   ├── __init__.py
   └── sample.py
└── tests
    └── test_sample.py

Simply put an empty conftest.py file in the project root directory, because when pytest discovers a conftest.py, it modifies sys.path so it can import stuff from the conftest module. A general directory structure can be:

Root
├── conftest.py
├── module1
│   ├── __init__.py
│   └── sample.py
└── tests
    └── test_sample.py

回答 20

有一个类似的问题,当我__init__.py在tests目录下添加文件时,它可以工作。

Had a similar issue and it worked when I added __init__.py file under tests directory.


回答 21

可能是因为Pytest并未将Python包作为Python模块读取(可能是由于路径问题)。尝试更改pytest脚本的目录或将模块显式添加到PYTHONPATH。

也可能是您的计算机上安装了两个版本的Python。检查您的Python源是否有pytest和您运行的python shell。如果它们不同(例如,Python 2 vs 3),请使用source activate来确保您正在为安装模块的相同python运行pytest。

It could be that Pytest is not reading the package as a Python module while Python is (likely due to path issues). Try changing the directory of the pytest script or adding the module explicitly to your PYTHONPATH.

Or it could be that you have two versions of Python installed on your machine. Check your Python source for pytest and for the python shell that you run. If they are different (i.e. Python 2 vs 3), use source activate to make sure that you are running the pytest installed for the same python that the module is installed in.


回答 22

对于任何尝试了一切但仍然出错的人,我都有解决方法。

安装pytest文件夹中,转到pytest-env文件夹。

打开 pyvenv.cfg文件。

在文件中,将include-system-site-packagesfalse更改为true

home = /usr/bin
include-system-site-packages = true
version = 3.6.6

希望它能起作用。不要忘记投票。

For anyone who tried everything and still getting error,I have a work around.

In the folder where pytest is installed,go to pytest-env folder.

Open pyvenv.cfg file.

In the file change include-system-site-packages from false to true.

home = /usr/bin
include-system-site-packages = true
version = 3.6.6

Hope it works .Don’t forget to up vote.


回答 23

如果您已经有.pyc文件,请尝试将其删除。

今天,我遇到了这个问题,这是发生了什么:

首先,我在Mac中运行pytest(这将生成pyc文件),然后启动安装了项目目录的docker容器(操作系统为alpine),然后尝试在容器中运行pytest时,发生ImportError。清除所有pyc文件后,再也没有错误。

希望这会有所帮助。

If you already have .pyc files, try to delete them.

Today, I encounter this problem, here is what happend:

first I run pytest in mac (this will generate pyc files) then I launch a docker container (the os is alpine), with project dir mounted, and then when I try to run pytest in container, ImportError happens. after cleaning all pyc files, no error any more.

Hope this may be helpful.


回答 24

如果您的文件夹中需要一个init .py文件,请制作该文件夹的副本,然后删除其中的init .py来运行您的测试,该测试适用于本地项目。如果需要定期运行测试,请查看是否可以将init .py移到单独的文件中。

if you need a init.py file in your folder make a copy of the folder and delete init.py in that one to run your tests it works for local projects. If you need to run test regularly see if you can move your init.py to a separate file.


回答 25

[解决]在直接进入删除/添加的解决方案之前__init__.py,我们可能还想看一下如何在您的类中完成导入。实际上,我只是__init__.py想着这可能是问题的原因,所以迷失了一天。)但是,那确实很有用。

就我而言,这是将类从一个python类调用到另一个正在抛出的python类的错误方式 ImportError。修复了类/模块的调用方式,它就像魅力一样工作。希望这对其他人也有帮助。

是的,对于类似的错误,根据代码的编写方式,我们可能有不同的解决方案。最好花更多时间进行自我调试。获得的经验:)编码愉快!!!

[Resolved] Before directly jumping into the solution of removing/ adding __init__.py, we might also want to look at how the imports are been done in your classes. Actually, I lost a day playing around with just __init__.py thinking that might be the problem :) However, that was quite informative.

In my case, it was the wrong way of calling classes from one python class to another python class which was throwing ImportError. Fixed the way classes/ modules to be called and it worked like charm. Hope, this helps others as well.

And yes, for similar error, we might have different solutions depending on how the code is written. Better to spend more time on self debugging. Lesson Learnt :) Happy coding!!!


回答 26

就我而言,我在一个容器中工作,不幸的是pytest倾向于使用python2.7而不是我选择的python3解释器。

就我而言,这可行:

python3 -m pytest

我的文件夹结构

/
app/
-module1.py
-module2.py
-tests/
--test_module1.py
--test_module2.py
requirements.txt
README.md

In my case I am working in a container and unfortuantely pytest has the tendency to use python2.7 rather than my python3 interpreter of choice.

In my case this worked:

python3 -m pytest

My folder structure

/
app/
-module1.py
-module2.py
-tests/
--test_module1.py
--test_module2.py
requirements.txt
README.md

回答 27

我已经将所有测试放在一个tests文件夹中,并且得到了相同的错误。我通过在该文件夹中添加init .py 来解决此问题,如下所示:

.
|-- Pipfile
|-- Pipfile.lock
|-- README.md
|-- api
|-- app.py
|-- config.py
|-- migrations
|-- pull_request_template.md
|-- settings.py
`-- tests
    |-- __init__.py <------
    |-- conftest.py
    `-- test_sample.py

I had placed all my tests in a tests folder and was getting the same error. I solved this by adding an init.py in that folder like so:

.
|-- Pipfile
|-- Pipfile.lock
|-- README.md
|-- api
|-- app.py
|-- config.py
|-- migrations
|-- pull_request_template.md
|-- settings.py
`-- tests
    |-- __init__.py <------
    |-- conftest.py
    `-- test_sample.py

Python:导入urllib.quote

问题:Python:导入urllib.quote

我想用urllib.quote()。但是python(python3)找不到模块。假设我有以下代码行:

print(urllib.quote("châteu", safe=''))

如何导入urllib.quote?

import urllibimport urllib.quote两者都给

AttributeError: 'module' object has no attribute 'quote'

令我困惑的urllib.request是可以通过以下方式访问import urllib.request

I would like to use urllib.quote(). But python (python3) is not finding the module. Suppose, I have this line of code:

print(urllib.quote("châteu", safe=''))

How do I import urllib.quote?

import urllib or import urllib.quote both give

AttributeError: 'module' object has no attribute 'quote'

What confuses me is that urllib.request is accessible via import urllib.request


回答 0

在Python 3.x中,您需要导入urllib.parse.quote

>>> import urllib.parse
>>> urllib.parse.quote("châteu", safe='')
'ch%C3%A2teu'

根据Python 2.x urllib模块文档

注意

urllib模块已经被分成部分和更名在Python 3 urllib.requesturllib.parse,和urllib.error

In Python 3.x, you need to import urllib.parse.quote:

>>> import urllib.parse
>>> urllib.parse.quote("châteu", safe='')
'ch%C3%A2teu'

According to Python 2.x urllib module documentation:

NOTE

The urllib module has been split into parts and renamed in Python 3 to urllib.request, urllib.parse, and urllib.error.


回答 1

如果您需要同时处理Python 2.x和3.x,则可以捕获异常并加载替代项。

try:
    from urllib import quote  # Python 2.X
except ImportError:
    from urllib.parse import quote  # Python 3+

您还可以使用python兼容性包装器6来处理此问题。

from six.moves.urllib.parse import quote

If you need to handle both Python 2.x and 3.x you can catch the exception and load the alternative.

try:
    from urllib import quote  # Python 2.X
except ImportError:
    from urllib.parse import quote  # Python 3+

You could also use the python compatibility wrapper six to handle this.

from six.moves.urllib.parse import quote

回答 2

urllib在Python3中进行了一些更改,现在可以从parse子模块中导入

>>> from urllib.parse import quote  
>>> quote('"')                      
'%22'                               

urllib went through some changes in Python3 and can now be imported from the parse submodule

>>> from urllib.parse import quote  
>>> quote('"')                      
'%22'                               

回答 3

这就是我在不使用异常的情况下的处理方式。

import sys
if sys.version_info.major > 2:  # Python 3 or later
    from urllib.parse import quote
else:  # Python 2
    from urllib import quote

This is how I handle this, without using exceptions.

import sys
if sys.version_info.major > 2:  # Python 3 or later
    from urllib.parse import quote
else:  # Python 2
    from urllib import quote

Python循环导入?

问题:Python循环导入?

所以我得到这个错误

Traceback (most recent call last):
  File "/Users/alex/dev/runswift/utils/sim2014/simulator.py", line 3, in <module>
    from world import World
  File "/Users/alex/dev/runswift/utils/sim2014/world.py", line 2, in <module>
    from entities.field import Field
  File "/Users/alex/dev/runswift/utils/sim2014/entities/field.py", line 2, in <module>
    from entities.goal import Goal
  File "/Users/alex/dev/runswift/utils/sim2014/entities/goal.py", line 2, in <module>
    from entities.post import Post
  File "/Users/alex/dev/runswift/utils/sim2014/entities/post.py", line 4, in <module>
    from physics import PostBody
  File "/Users/alex/dev/runswift/utils/sim2014/physics.py", line 21, in <module>
    from entities.post import Post
ImportError: cannot import name Post

并且您可以看到我进一步使用了相同的import语句,并且有效吗?关于循环导入是否有一些不成文的规定?如何在调用堆栈的更下方使用相同的类?

So i’m getting this error

Traceback (most recent call last):
  File "/Users/alex/dev/runswift/utils/sim2014/simulator.py", line 3, in <module>
    from world import World
  File "/Users/alex/dev/runswift/utils/sim2014/world.py", line 2, in <module>
    from entities.field import Field
  File "/Users/alex/dev/runswift/utils/sim2014/entities/field.py", line 2, in <module>
    from entities.goal import Goal
  File "/Users/alex/dev/runswift/utils/sim2014/entities/goal.py", line 2, in <module>
    from entities.post import Post
  File "/Users/alex/dev/runswift/utils/sim2014/entities/post.py", line 4, in <module>
    from physics import PostBody
  File "/Users/alex/dev/runswift/utils/sim2014/physics.py", line 21, in <module>
    from entities.post import Post
ImportError: cannot import name Post

and you can see that i use the same import statement further up and it works? Is there some unwritten rule about circular importing? How do i use the same class further down the call stack?


回答 0

我认为jpmc26的答案,但绝不是错误的,但在循环进口方面却过于严格。如果正确设置它们,它们可以正常工作。

最简单的方法是使用import my_module语法,而不是from my_module import some_object。前者几乎总是可以工作,即使my_module包括在内也能使我们重新受益。后者只有在my_object中已经定义时才有效my_module,在循环导入中可能不是这种情况。

要针对您的具体情况:尝试更改entities/post.py为do import physics,然后引用physics.PostBody而不是PostBody直接引用。同样,更改physics.py为do import entities.post,然后使用entities.post.Post而不是just Post

I think the answer by jpmc26, while by no means wrong, comes down too heavily on circular imports. They can work just fine, if you set them up correctly.

The easiest way to do so is to use import my_module syntax, rather than from my_module import some_object. The former will almost always work, even if my_module included imports us back. The latter only works if my_object is already defined in my_module, which in a circular import may not be the case.

To be specific to your case: Try changing entities/post.py to do import physics and then refer to physics.PostBody rather than just PostBody directly. Similarly, change physics.py to do import entities.post and then use entities.post.Post rather than just Post.


回答 1

首次导入模块(或其成员)时,模块内的代码将像其他任何代码一样顺序执行。例如,对函数主体的处理没有任何区别。An import只是一个与其他命令一样的命令(赋值,函数调用defclass)。假设您的导入发生在脚本的顶部,那么将发生以下情况:

  • 当您尝试从导入Worldworldworld脚本将被执行。
  • world脚本的进口Field,这将导致entities.field脚本得到执行。
  • 这个过程一直持续到您到达entities.post脚本为止,因为您尝试导入Post
  • entities.post脚本导致physics模块被执行,因为它尝试导入PostBody
  • 最后,physics尝试Postentities.post
  • 我不确定该entities.post模块是否已存在于内存中,但这并不重要。该模块不在内存中,或者该模块还没有Post成员,因为该模块尚未完成执行定义Post
  • 无论哪种方式,都会发生错误,因为Post那里没有要导入的错误

因此,它不是“在调用堆栈中进一步发挥作用”。这是错误发生位置的堆栈跟踪,这意味着它在尝试导入Post该类时出错。您不应该使用循环导入。充其量,它的收益微不足道(通常没有收益),并且会引起类似的问题。这给所有开发人员维护它带来了负担,迫使他们在蛋壳上行走以避免损坏它。重构您的模块组织。

When you import a module (or a member of it) for the first time, the code inside the module is executed sequentially like any other code; e.g., it is not treated any differently that the body of a function. An import is just a command like any other (assignment, a function call, def, class). Assuming your imports occur at the top of the script, then here’s what’s happening:

  • When you try to import World from world, the world script gets executed.
  • The world script imports Field, which causes the entities.field script to get executed.
  • This process continues until you reach the entities.post script because you tried to import Post
  • The entities.post script causes physics module to be executed because it tries to import PostBody
  • Finally, physics tries to import Post from entities.post
  • I’m not sure whether the entities.post module exists in memory yet, but it really doesn’t matter. Either the module is not in memory, or the module doesn’t yet have a Post member because it hasn’t finished executing to define Post
  • Either way, an error occurs because Post is not there to be imported

So no, it’s not “working further up in the call stack”. This is a stack trace of where the error occurred, which means it errored out trying to import Post in that class. You shouldn’t use circular imports. At best, it has negligible benefit (typically, no benefit), and it causes problems like this. It burdens any developer maintaining it, forcing them to walk on egg shells to avoid breaking it. Refactor your module organization.


回答 2

要了解循环依赖关系,您需要记住Python本质上是一种脚本语言。方法外部的语句执行在编译时发生。导入语句的执行就像方法调用一样,要理解它们,您应该像方法调用一样考虑它们。

导入时,发生的情况取决于模块表中是否已存在要导入的文件。如果是这样,Python将使用符号表中当前使用的任何内容。如果没有,Python将开始读取模块文件,编译/执行/导入其找到的文件。是否找到在编译时引用的符号,具体取决于编译器是否已看到它们。

假设您有两个源文件:

文件X.py

def X1:
    return "x1"

from Y import Y2

def X2:
    return "x2"

文件Y.py

def Y1:
    return "y1"

from X import X1

def Y2:
    return "y2"

现在假设您编译文件X.py。编译器首先定义方法X1,然后在X.py中命中import语句。这将导致编译器暂停X.py的编译并开始编译Y.py。此后不久,编译器在Y.py中命中import语句。由于X.py已经在模块表中,因此Python使用现有的不完整X.py符号表来满足请求的所有引用。现在,X.py中import语句之前出现的所有符号都在符号表中,但之后的任何符号都没有。由于X1现在出现在import语句之前,因此已成功导入。然后,Python恢复编译Y.py。这样,它定义了Y2并完成了Y.py的编译。然后,它恢复X.py的编译,并在Y.py符号表中找到Y2。编译最终完成,没有错误。

如果尝试从命令行编译Y.py,则会发生非常不同的事情。在编译Y.py时,编译器会在定义Y2之前命中import语句。然后,它开始编译X.py。很快,它在X.py中命中了需要Y2的import语句。但是Y2是未定义的,因此编译失败。

请注意,如果您将X.py修改为导入Y1,则无论您编译哪个文件,编译都将始终成功。但是,如果修改文件Y.py以导入符号X2,则两个文件都不会编译。

每当模块X或X导入的任何模块可能导入当前模块时,请勿使用:

from X import Y

每当您认为可能会有循环导入时,也应避免在编译时引用其他模块中的变量。考虑一下看起来纯真的代码:

import X
z = X.Y

假设模块X在此模块导入X之前先导入此模块。进一步假设Y在import语句后的X中定义。然后,在导入此模块时将不会定义Y,并且会出现编译错误。如果此模块首先导入Y,那么您可以摆脱它。但是,当您的一位同事无辜地更改第三个模块中的定义顺序时,代码将中断。

在某些情况下,您可以通过将导入语句下移到其他模块所需的符号定义下方来解决循环依赖性。在上面的示例中,import语句之前的定义永远不会失败。取决于编译的顺序,import语句之后的定义有时会失败。您甚至可以将import语句放在文件的末尾,只要在编译时不需要任何导入的符号即可。

请注意,将导入语句在模块中下移会掩盖您的操作。为此,请在模块顶部添加注释,如下所示:

#import X   (actual import moved down to avoid circular dependency)

通常,这是一个不好的做法,但有时很难避免。

To understand circular dependencies, you need to remember that Python is essentially a scripting language. Execution of statements outside methods occurs at compile time. Import statements are executed just like method calls, and to understand them you should think about them like method calls.

When you do an import, what happens depends on whether the file you are importing already exists in the module table. If it does, Python uses whatever is currently in the symbol table. If not, Python begins reading the module file, compiling/executing/importing whatever it finds there. Symbols referenced at compile time are found or not, depending on whether they have been seen, or are yet to be seen by the compiler.

Imagine you have two source files:

File X.py

def X1:
    return "x1"

from Y import Y2

def X2:
    return "x2"

File Y.py

def Y1:
    return "y1"

from X import X1

def Y2:
    return "y2"

Now suppose you compile file X.py. The compiler begins by defining the method X1, and then hits the import statement in X.py. This causes the compiler to pause compilation of X.py and begin compiling Y.py. Shortly thereafter the compiler hits the import statement in Y.py. Since X.py is already in the module table, Python uses the existing incomplete X.py symbol table to satisfy any references requested. Any symbols appearing before the import statement in X.py are now in the symbol table, but any symbols after are not. Since X1 now appears before the import statement, it is successfully imported. Python then resumes compiling Y.py. In doing so it defines Y2 and finishes compiling Y.py. It then resumes compilation of X.py, and finds Y2 in the Y.py symbol table. Compilation eventually completes w/o error.

Something very different happens if you attempt to compile Y.py from the command line. While compiling Y.py, the compiler hits the import statement before it defines Y2. Then it starts compiling X.py. Soon it hits the import statement in X.py that requires Y2. But Y2 is undefined, so the compile fails.

Please note that if you modify X.py to import Y1, the compile will always succeed, no matter which file you compile. However if you modify file Y.py to import symbol X2, neither file will compile.

Any time when module X, or any module imported by X might import the current module, do NOT use:

from X import Y

Any time you think there may be a circular import you should also avoid compile time references to variables in other modules. Consider the innocent looking code:

import X
z = X.Y

Suppose module X imports this module before this module imports X. Further suppose Y is defined in X after the import statement. Then Y will not be defined when this module is imported, and you will get a compile error. If this module imports Y first, you can get away with it. But when one of your co-workers innocently changes the order of definitions in a third module, the code will break.

In some cases you can resolve circular dependencies by moving an import statement down below symbol definitions needed by other modules. In the examples above, definitions before the import statement never fail. Definitions after the import statement sometimes fail, depending on the order of compilation. You can even put import statements at the end of a file, so long as none of the imported symbols are needed at compile time.

Note that moving import statements down in a module obscures what you are doing. Compensate for this with a comment at the top of your module something like the following:

#import X   (actual import moved down to avoid circular dependency)

In general this is a bad practice, but sometimes it is difficult to avoid.


回答 3

对于像我一样从Django来解决此问题的人,您应该知道该文档提供了一种解决方案:https : //docs.djangoproject.com/en/1.10/ref/models/fields/#foreignkey

“ …要引用在另一个应用程序中定义的模型,您可以显式指定带有完整应用程序标签的模型。例如,如果上述制造商模型是在另一个名为production的应用程序中定义的,则需要使用:

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'production.Manufacturer',
        on_delete=models.CASCADE,
)

解决两个应用程序之间的循环导入依赖关系时,此类参考很有用。…”

For those of you who, like me, come to this issue from Django, you should know that the docs provide a solution: https://docs.djangoproject.com/en/1.10/ref/models/fields/#foreignkey

“…To refer to models defined in another application, you can explicitly specify a model with the full application label. For example, if the Manufacturer model above is defined in another application called production, you’d need to use:

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'production.Manufacturer',
        on_delete=models.CASCADE,
)

This sort of reference can be useful when resolving circular import dependencies between two applications.…”


回答 4

我能够(仅)将需要该模块中对象的功能导入模块:

def my_func():
    import Foo
    foo_instance = Foo()

I was able to import the module within the function (only) that would require the objects from this module:

def my_func():
    import Foo
    foo_instance = Foo()

回答 5

如果您在一个相当复杂的应用程序中遇到此问题,那么重构所有导入文件可能会很麻烦。PyCharm为此提供了一个快速修复程序,该修复程序还将自动更改导入符号的所有用法。

If you run into this issue in a fairly complex app it can be cumbersome to refactor all your imports. PyCharm offers a quickfix for this that will automatically change all usage of the imported symbols as well.


回答 6

我正在使用以下内容:

from module import Foo

foo_instance = Foo()

但摆脱掉circular reference我做了以下工作,它的工作:

import module.foo

foo_instance = foo.Foo()

I was using the following:

from module import Foo

foo_instance = Foo()

but to get rid of circular reference I did the following and it worked:

import module.foo

foo_instance = foo.Foo()

将Python搜索路径扩展到其他来源

问题:将Python搜索路径扩展到其他来源

我刚刚加入了一个具有相当大的现有代码库的项目。我们用linux开发,不使用和IDE。我们通过命令行运行。我试图弄清楚如何在运行项目模块时让python搜索正确的路径。例如,当我运行类似的内容时:

python someprojectfile.py

我懂了

ImportError: no module named core.'somemodule'

我认为所有导入的内容都是这样,我认为这是路径问题。

TLDR:

如何~/codez/project/在导入语句期间让Python搜索* .py文件以及所有文件和文件夹。

I have just joined a project with a rather large existing code base. We develop in linux and do not use and IDE. We run through the command line. I’m trying to figure out how to get python to search for the right path when I run project modules. For instance, when I run something like:

python someprojectfile.py

I get

ImportError: no module named core.'somemodule'

I get this for all of my imports to I assume it’s an issue with the path.

TLDR:

How do I get Python to search ~/codez/project/ and all the files and folders for *.py files during import statements.


回答 0

有几种方法可以做到这一点:

  • 将环境变量设置PYTHONPATH为用冒号分隔的目录列表,以搜索导入的模块。
  • 在您的程序中,用于sys.path.append('/path/to/search')添加您希望Python搜索导入的模块的目录名称。sys.path只是Python在每次被要求导入模块时搜索的目录列表,您可以根据需要进行更改(尽管我不建议删除任何标准目录!)。Python启动时,您放入环境变量中的所有目录PYTHONPATH都将插入sys.path其中。
  • 用于site.addsitedir向添加目录sys.path。此和纯附加的区别在于,当您使用时addsitedir,它还会.pth在该目录中查找文件,并使用它们sys.path根据文件的内容向其中添加其他目录。有关更多详细信息,请参见文档。

您要使用哪一种取决于您的情况。请记住,当您将项目分发给其他用户时,他们通常会以某种方式安装该项目,以便Python的导入程序会自动检测到Python代码文件(即,程序包通常安装在site-packages目录中),因此,如果您弄乱了sys.path代码,当该代码在另一台计算机上运行时,可能是不必要的,甚至可能产生不利影响。对于开发而言,我会大胆猜测设置PYTHONPATH通常是最好的选择。

但是,当您使用仅在自己的计算机上运行的内容时(或当您进行非标准设置时(例如有时在Web应用程序框架中)),执行诸如此类的操作并非完全不常见。

import sys
from os.path import dirname
sys.path.append(dirname(__file__))

There are a few possible ways to do this:

  • Set the environment variable PYTHONPATH to a colon-separated list of directories to search for imported modules.
  • In your program, use sys.path.append('/path/to/search') to add the names of directories you want Python to search for imported modules. sys.path is just the list of directories Python searches every time it gets asked to import a module, and you can alter it as needed (although I wouldn’t recommend removing any of the standard directories!). Any directories you put in the environment variable PYTHONPATH will be inserted into sys.path when Python starts up.
  • Use site.addsitedir to add a directory to sys.path. The difference between this and just plain appending is that when you use addsitedir, it also looks for .pth files within that directory and uses them to possibly add additional directories to sys.path based on the contents of the files. See the documentation for more detail.

Which one of these you want to use depends on your situation. Remember that when you distribute your project to other users, they typically install it in such a manner that the Python code files will be automatically detected by Python’s importer (i.e. packages are usually installed in the site-packages directory), so if you mess with sys.path in your code, that may be unnecessary and might even have adverse effects when that code runs on another computer. For development, I would venture a guess that setting PYTHONPATH is usually the best way to go.

However, when you’re using something that just runs on your own computer (or when you have nonstandard setups, e.g. sometimes in web app frameworks), it’s not entirely uncommon to do something like

import sys
from os.path import dirname
sys.path.append(dirname(__file__))

回答 1

您还应该在这里阅读有关python软件包的信息:http : //docs.python.org/tutorial/modules.html

从您的示例中,我想您确实在拥有一个软件包~/codez/project__init__.pypython目录中的文件将目录映射到命名空间。如果所有子目录都有一个__init__.py文件,则只需将基本目录添加到中PYTHONPATH。例如:

PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis / project

正如David解释的那样,除了测试您的PYTHONPATH环境变量外,您还可以像这样在python中对其进行测试:

$ python
>>> import project                      # should work if PYTHONPATH set
>>> import sys
>>> for line in sys.path: print line    # print current python path

You should also read about python packages here: http://docs.python.org/tutorial/modules.html.

From your example, I would guess that you really have a package at ~/codez/project. The file __init__.py in a python directory maps a directory into a namespace. If your subdirectories all have an __init__.py file, then you only need to add the base directory to your PYTHONPATH. For example:

PYTHONPATH=$PYTHONPATH:$HOME/adaifotis/project

In addition to testing your PYTHONPATH environment variable, as David explains, you can test it in python like this:

$ python
>>> import project                      # should work if PYTHONPATH set
>>> import sys
>>> for line in sys.path: print line    # print current python path


回答 2

我知道这个线程有些陈旧,但是花了我一些时间才能真正理解这一点,所以我想分享一下。

在我的项目中,我的主脚本位于父目录中,为了区分模块,我将所有支持的模块放在一个称为“模块”的子文件夹中。在我的主脚本中,我像这样导入这些模块(对于名为report.py的模块):

from modules.report import report, reportError

如果我调用主脚本,则可以正常工作。但是,我想通过main()在每个模块中包含一个并直接调用每个模块来测试每个模块,如下所示:

python modules/report.py

现在,Python抱怨它找不到“称为模块的模块”。这里的关键是,默认情况下,Python在其搜索路径中包括脚本的文件夹,但不是CWD。因此,此错误实际上表示“我找不到模块子文件夹”。这是因为report.py模块所在的目录中没有“ modules”子目录。

我发现最巧妙的解决方案是通过在顶部包括以下内容来将CWD附加到Python搜索路径中:

import sys

sys.path.append(".")

现在,Python搜索CWD(当前目录),找到“模块”子文件夹,一切顺利。

I know this thread is a bit old, but it took me some time to get to the heart of this, so I wanted to share.

In my project, I had the main script in a parent directory, and, to differentiate the modules, I put all the supporting modules in a sub-folder called “modules”. In my main script, I import these modules like this (for a module called report.py):

from modules.report import report, reportError

If I call my main script, this works. HOWEVER, I wanted to test each module by including a main() in each, and calling each directly, as:

python modules/report.py

Now Python complains that it can’t find “a module called modules”. The key here is that, by default, Python includes the folder of the script in its search path, BUT NOT THE CWD. So what this error says, really, is “I can’t find a modules subfolder”. The is because there is no “modules” subdirectory from the directory where the report.py module resides.

I find that the neatest solution to this is to append the CWD in Python search path by including this at the top:

import sys

sys.path.append(".")

Now Python searches the CWD (current directory), finds the “modules” sub-folder, and all is well.


回答 3

我阅读了此问题以寻找答案,但不喜欢其中任何一个。

所以我写了一个快速而肮脏的解决方案。只需将其放在sys.path上的某个位置,它将在folder(来自当前工作目录)或下添加任何目录abspath

#using.py

import sys, os.path

def all_from(folder='', abspath=None):
    """add all dirs under `folder` to sys.path if any .py files are found.
    Use an abspath if you'd rather do it that way.

    Uses the current working directory as the location of using.py. 
    Keep in mind that os.walk goes *all the way* down the directory tree.
    With that, try not to use this on something too close to '/'

    """
    add = set(sys.path)
    if abspath is None:
        cwd = os.path.abspath(os.path.curdir)
        abspath = os.path.join(cwd, folder)
    for root, dirs, files in os.walk(abspath):
        for f in files:
            if f[-3:] in '.py':
                add.add(root)
                break
    for i in add: sys.path.append(i)

>>> import using, sys, pprint
>>> using.all_from('py') #if in ~, /home/user/py/
>>> pprint.pprint(sys.path)
[
#that was easy
]

我之所以喜欢它,是因为我可以为一些随机工具提供一个文件夹,而不必让它们成为软件包或任何东西的一部分,并且仍然可以通过几行代码访问其中的一些(或全部)。

I read this question looking for an answer, and didn’t like any of them.

So I wrote a quick and dirty solution. Just put this somewhere on your sys.path, and it’ll add any directory under folder (from the current working directory), or under abspath:

#using.py

import sys, os.path

def all_from(folder='', abspath=None):
    """add all dirs under `folder` to sys.path if any .py files are found.
    Use an abspath if you'd rather do it that way.

    Uses the current working directory as the location of using.py. 
    Keep in mind that os.walk goes *all the way* down the directory tree.
    With that, try not to use this on something too close to '/'

    """
    add = set(sys.path)
    if abspath is None:
        cwd = os.path.abspath(os.path.curdir)
        abspath = os.path.join(cwd, folder)
    for root, dirs, files in os.walk(abspath):
        for f in files:
            if f[-3:] in '.py':
                add.add(root)
                break
    for i in add: sys.path.append(i)

>>> import using, sys, pprint
>>> using.all_from('py') #if in ~, /home/user/py/
>>> pprint.pprint(sys.path)
[
#that was easy
]

And I like it because I can have a folder for some random tools and not have them be a part of packages or anything, and still get access to some (or all) of them in a couple lines of code.


回答 4

我发现最简单的方法是创建一个文件“ any_name.pth”,并将其放在文件夹“ \ Lib \ site-packages”中。您应该在安装python的任何位置都找到该文件夹​​。

在该文件中,放入要保留要导入模块的目录列表。例如,在该文件中这样一行:

C:\ Users \ example … \ example

您可以通过在python中运行它来告诉它工作:

import sys
for line in sys: print line

您将看到已打印的目录,以及从中可以导入的目录。现在,您可以轻松地导入该目录中的“ mymodule.py”文件:

import mymodule

这将不会导入子文件夹。为此,您可以想象创建一个python脚本来创建一个.pth文件,其中包含您定义的文件夹的所有子文件夹。让它在启动时运行。

The easiest way I find is to create a file “any_name.pth” and put it in your folder “\Lib\site-packages”. You should find that folder wherever python is installed.

In that file, put a list of directories where you want to keep modules for importing. For instance, make a line in that file like this:

C:\Users\example…\example

You will be able to tell it works by running this in python:

import sys
for line in sys: print line

You will see your directory printed out, amongst others from where you can also import. Now you can import a “mymodule.py” file that sits in that directory as easily as:

import mymodule

This will not import subfolders. For that you could imagine creating a python script to create a .pth file containing all sub folders of a folder you define. Have it run at startup perhaps.


回答 5

旧问题的新选择。在Debian上
安装fail2ban软件包,看起来像是硬编码安装/usr/lib/python3/dist-packages/fail2ban在python3以外的路径上sys.path


> python3
Python 3.7.3 (v3.7.3:ef4ec6ed12, Jun 25 2019, 18:51:50)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/lib/python3.7/site-packages']
>>>

因此,我(bash)将库链接到较新的版本,而不仅仅是复制。
将来对原始应用程序的更新也将自动应用于链接版本。

 if [ -d /usr/lib/python3/dist-packages/fail2ban ]
   then
      for d in /usr/lib/python3.*
      do
         [ -d ${d}/fail2ban ] || \
            ln -vs /usr/lib/python3/dist-packages/fail2ban ${d}/
      done
   fi

New option for old question.
Installing fail2ban package on Debian, looks like it’s hardcoded to install on /usr/lib/python3/dist-packages/fail2ban a path not on python3 sys.path.


> python3
Python 3.7.3 (v3.7.3:ef4ec6ed12, Jun 25 2019, 18:51:50)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/lib/python3.7/site-packages']
>>>

so, instead of just copying, I (bash) linked the library to newer versions.
Future updates to the original app, will also be automatically applied to the linked versions.

 if [ -d /usr/lib/python3/dist-packages/fail2ban ]
   then
      for d in /usr/lib/python3.*
      do
         [ -d ${d}/fail2ban ] || \
            ln -vs /usr/lib/python3/dist-packages/fail2ban ${d}/
      done
   fi

如何从另一个模块更改模块变量?

问题:如何从另一个模块更改模块变量?

假设我有一个名为的软件包bar,其中包含bar.py

a = None

def foobar():
    print a

__init__.py

from bar import a, foobar

然后我执行以下脚本:

import bar

print bar.a
bar.a = 1
print bar.a
bar.foobar()

这是我的期望:

None
1
1

这是我得到的:

None
1
None

谁能解释我的误解?

Suppose I have a package named bar, and it contains bar.py:

a = None

def foobar():
    print a

and __init__.py:

from bar import a, foobar

Then I execute this script:

import bar

print bar.a
bar.a = 1
print bar.a
bar.foobar()

Here’s what I expect:

None
1
1

Here’s what I get:

None
1
None

Can anyone explain my misconception?


回答 0

您正在使用from bar import aa在导入模块的全局范围(或​​发生import语句的任何范围)中成为符号。

当您为指定新值时a,您也只是在更改哪些值a,而不是实际值。尝试bar.py直接使用import barin 导入,__init__.py并通过设置在那里进行实验bar.a = 1。这样,您实际上将在此上下文中修改bar.__dict__['a']哪个是“实际”值a

它有点复杂,分为三层,但是bar.a = 1更改了实际上是从派生a的模块中的值。它不会更改所看到的值,因为它存在于实际文件中。您可以设置是否要更改它。bar__init__.pyafoobarfoobarbar.pybar.bar.a

这是使用语句from foo import bar形式的危险之一import:它将分成bar两个符号,一个符号在全局范围内可见,从foo该符号开始指向原始值,而另一个符号在import执行该语句的范围内可见。更改符号指向的位置也不会更改其指向的值。

尝试reload从交互式解释器访问模块时,这种东西是致命的。

You are using from bar import a. a becomes a symbol in the global scope of the importing module (or whatever scope the import statement occurs in).

When you assign a new value to a, you are just changing which value a points too, not the actual value. Try to import bar.py directly with import bar in __init__.py and conduct your experiment there by setting bar.a = 1. This way, you will actually be modifying bar.__dict__['a'] which is the ‘real’ value of a in this context.

It’s a little convoluted with three layers but bar.a = 1 changes the value of a in the module called bar that is actually derived from __init__.py. It does not change the value of a that foobar sees because foobar lives in the actual file bar.py. You could set bar.bar.a if you wanted to change that.

This is one of the dangers of using the from foo import bar form of the import statement: it splits bar into two symbols, one visible globally from within foo which starts off pointing to the original value and a different symbol visible in the scope where the import statement is executed. Changing a where a symbol points doesn’t change the value that it pointed too.

This sort of stuff is a killer when trying to reload a module from the interactive interpreter.


回答 1

这个问题困难的一个原因是,你有一个名为程序bar/bar.pyimport bar可导入bar/__init__.pybar/bar.py,取决于它完成,这使得它有点笨重跟踪哪些abar.a

下面是它的工作原理:

了解发生了什么事情的关键是要意识到自己__init__.py

from bar import a

实际上做了类似的事情

a = bar.a
# … where bar = bar/bar.py (as if bar were imported locally from __init__.py)

并定义一个新变量(bar/__init__.py:a,如果需要的话)。因此,您的from bar import ain __init__.py会将名称绑定bar/__init__.py:a到原始bar.py:a对象(None)。这就是为什么你可以做from bar import a as a2__init__.py:在这种情况下,很显然,你有两个bar/bar.py:a和一个不同的变量名bar/__init__.py:a2(在你的情况下,这两个变量的名字恰好两者a,但他们仍然生活在不同的命名空间:在__init__.py,它们是bar.aa)。

现在,当你做

import bar

print bar.a

您正在访问变量bar/__init__.py:a(因为import bar导入了your bar/__init__.py)。这是您修改的变量(为1)。您没有触及variable的内容bar/bar.py:a。所以当你随后做

bar.foobar()

您调用bar/bar.py:foobar(),它将访问a来自的变量bar/bar.py,后者仍然是Nonefoobar()定义后,它将一劳永逸地绑定变量名称,因此ain bar.pybar.py:a,而不是a另一个模块中定义的任何其他变量-因为a在所有导入的模块中可能有很多变量)。因此是最后一个None输出。

结论:最好是避免任何含糊之处import bar,由具有任何bar/bar.py模块(因为bar.__init__.py品牌目录bar/包已经,您还可以导入import bar)。

One source of difficulty with this question is that you have a program named bar/bar.py: import bar imports either bar/__init__.py or bar/bar.py, depending on where it is done, which makes it a little cumbersome to track which a is bar.a.

Here is how it works:

The key to understanding what happens is to realize that in your __init__.py,

from bar import a

in effect does something like

a = bar.a
# … where bar = bar/bar.py (as if bar were imported locally from __init__.py)

and defines a new variable (bar/__init__.py:a, if you wish). Thus, your from bar import a in __init__.py binds name bar/__init__.py:a to the original bar.py:a object (None). This is why you can do from bar import a as a2 in __init__.py: in this case, it is clear that you have both bar/bar.py:a and a distinct variable name bar/__init__.py:a2 (in your case, the names of the two variables just happen to both be a, but they still live in different namespaces: in __init__.py, they are bar.a and a).

Now, when you do

import bar

print bar.a

you are accessing variable bar/__init__.py:a (since import bar imports your bar/__init__.py). This is the variable you modify (to 1). You are not touching the contents of variable bar/bar.py:a. So when you subsequently do

bar.foobar()

you call bar/bar.py:foobar(), which accesses variable a from bar/bar.py, which is still None (when foobar() is defined, it binds variable names once and for all, so the a in bar.py is bar.py:a, not any other a variable defined in another module—as there might be many a variables in all the imported modules). Hence the last None output.

Conclusion: it is best to avoid any ambiguity in import bar, by not having any bar/bar.py module (since bar.__init__.py makes directory bar/ a package already, that you can also import with import bar).


回答 2

换一种说法:事实证明,这种误解很容易造成。 它是在Python语言参考中偷偷地定义的:使用object而不是symbol。我建议使用Python语言参考使这一点更清晰,更稀疏。

from形式不结合模块名称:它通过标识符的列表,看起来它们中的每一个向上的模块中,在步骤(1)中发现,并结合在本地命名空间中的名称对象从而找到。

然而:

导入时,将导入已导入符号的当前值,并将其添加到已定义的命名空间中。 您不是在导入参考,而是在有效导入值。

因此,要获取的更新值i,必须导入一个变量,该变量包含对该符号的引用。

换句话说,导入import与JAVA中的,externalC / C ++中的声明甚use至PERL中的子句都不一样。

而是在Python中执行以下语句:

from some_other_module import a as x

是更喜欢在K&R C下面的代码:

extern int a; /* import from the EXTERN file */

int x = a;

(注意:在Python情况下,“ a”和“ x”本质上是对实际值的引用:您不是在复制INT,而是在复制引用地址)

To put another way: Turns out this misconception is very easy to make. It is sneakily defined in the Python language reference: the use of object instead of symbol. I would suggest that the Python language reference make this more clear and less sparse..

The from form does not bind the module name: it goes through the list of identifiers, looks each one of them up in the module found in step (1), and binds the name in the local namespace to the object thus found.

HOWEVER:

When you import, you import the current value of the imported symbol and add it to your namespace as defined. You are not importing a reference, you are effectively importing a value.

Thus, to get the updated value of i, you must import a variable that holds a reference to that symbol.

In other words, importing is NOT like an import in JAVA, external declaration in C/C++ or even a use clause in PERL.

Rather, the following statement in Python:

from some_other_module import a as x

is more like the following code in K&R C:

extern int a; /* import from the EXTERN file */

int x = a;

(caveat: in the Python case, “a” and “x” are essentially a reference to the actual value: you’re not copying the INT, you’re copying the reference address)


从子文件夹导入模块

问题:从子文件夹导入模块

我想将子文件夹作为模块导入。因此,每个子文件夹都包含一个__init__.py。我的文件夹结构是这样的:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

在我的主脚本中,导入

from dirFoo.foofactory import FooFactory

在此工厂文件中,我包括以下子模块:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

如果我叫我的foofactory我得到了错误,那说明python无法导入子模块foo1和foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1

I want to import subfolders as modules. Therefore every subfolder contains a __init__.py. My folder structure is like this:

src\
  main.py
  dirFoo\
    __init__.py
    foofactory.py
    dirFoo1\
      __init__.py
      foo1.py
    dirFoo2\
      __init__.py
      foo2.py

In my main script I import

from dirFoo.foofactory import FooFactory

In this factory file I include the sub modules:

from dirFoo1.foo1 import Foo1
from dirFoo2.foo2 import Foo2

If I call my foofactory I get the error, that python can’t import the submodules foo1 and foo2:

Traceback (most recent call last):
  File "/Users/tmp/src/main.py", line 1, in <module>
from dirFoo.foofactory import FooFactory
  File "/Users/tmp/src/dirFoo/foofactory.py", line 1, in    <module>
from dirFoo1.foo1 import Foo1
    ImportError: No module named dirFoo1.foo1

回答 0

无需与您PYTHONPATHsys.path此处混淆。

为了在包中正确使用绝对导入,还应该包括“ root”包名,例如:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

或者您可以使用相对导入

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2

There’s no need to mess with your PYTHONPATH or sys.path here.

To properly use absolute imports in a package you should include the “root” packagename as well, e.g.:

from dirFoo.dirFoo1.foo1 import Foo1
from dirFoo.dirFoo2.foo2 import Foo2

Or you can use relative imports:

from .dirfoo1.foo1 import Foo1
from .dirfoo2.foo2 import Foo2

回答 1

只是在这里通知。(来自新蜜蜂keviv22)

永远不要为了自己的利益而用“-”或“ _”之类的符号命名文件夹或文件。如果这样做,您可能会遇到一些问题。就像我的一样,尽管导入命令正确无误,但您将无法成功导入所需的文件,这些文件在此类命名文件夹中可用。

无效的文件夹命名如下:

  • 通用类文件夹
  • Generic_Classes_Folder

上面的有效文件夹命名:

  • GenericClassesFolder或Genericclassesfolder或genericClassesFolder(或类似的词,单词之间没有任何空格或特殊符号)

我犯了什么错误:

考虑文件结构。

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

我想做什么?

  • 从testFile.py,我想在Generic-Class-Folder文件中导入“ targetClass.py”文件,以在“ targetClass.py”文件中使用名为“ functionExecute”的函数

我做了什么命令?

  • 来自“ testFile.py”,写了命令, from Core.Generic-Class-Folder.targetClass import functionExecute
  • 有类似的错误 SyntaxError: invalid syntax

尝试了许多搜索并查看了许多stackoverflow问题,但无法确定出了什么问题。我多次交叉检查文件,使用__init__.py文件,插入环境路径,非常担心出了什么问题……

在很长很长一段时间后,我在和我的一个朋友交谈时想出了这一点。使用这样的命名约定我并不傻。我绝对不要使用空格或特殊符号为任何文件夹或文件定义名称。所以,这就是我想传达的。祝你有美好的一天!

(很抱歉在此发布大量文章……只是让我的挫败感….::)谢谢!)

Just to notify here. (from a newbee, keviv22)

Never and ever for the sake of your own good, name the folders or files with symbols like “-” or “_”. If you did so, you may face few issues. like mine, say, though your command for importing is correct, you wont be able to successfully import the desired files which are available inside such named folders.

Invalid Folder namings as follows:

  • Generic-Classes-Folder
  • Generic_Classes_Folder

valid Folder namings for above:

  • GenericClassesFolder or Genericclassesfolder or genericClassesFolder (or like this without any spaces or special symbols among the words)

What mistake I did:

consider the file structure.

Parent
   . __init__.py
   . Setup
     .. __init__.py
     .. Generic-Class-Folder
        ... __init__.py
        ... targetClass.py
   . Check
     .. __init__.py
     .. testFile.py

What I wanted to do?

  • from testFile.py, I wanted to import the ‘targetClass.py’ file inside the Generic-Class-Folder file to use the function named “functionExecute” in ‘targetClass.py’ file

What command I did?

  • from ‘testFile.py’, wrote command, from Core.Generic-Class-Folder.targetClass import functionExecute
  • Got errors like SyntaxError: invalid syntax

Tried many searches and viewed many stackoverflow questions and unable to decide what went wrong. I cross checked my files multiple times, i used __init__.py file, inserted environment path and hugely worried what went wrong……

And after a long long long time, i figured this out while talking with a friend of mine. I am little stupid to use such naming conventions. I should never use space or special symbols to define a name for any folder or file. So, this is what I wanted to convey. Have a good day!

(sorry for the huge post over this… just letting my frustrations go…. :) Thanks!)


回答 2

设置您的PYTHONPATH环境变量。例如这样的PYTHONPATH =。:..(对于* nix系列)。

您也可以手动将当前目录(在您的情况下为src)添加到pythonpath中:

import os
import sys
sys.path.insert(0, os.getcwd())

Set your PYTHONPATH environment variable. For example like this PYTHONPATH=.:.. (for *nix family).

Also you can manually add your current directory (src in your case) to pythonpath:

import os
import sys
sys.path.insert(0, os.getcwd())

回答 3

假设您的项目采用以下结构:

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

run.py,您可以通过以下方式导入脚本一和二:

from subscripts import script_one as One
from subscripts import script_two as Two

现在,仍然在内run.py,您可以使用以下命令调用其方法:

One.method_from_one(param)
Two.method_from_two(other_param)

Say your project is structured this way:

+---MyPythonProject
|   +---.gitignore
|   +---run.py
|   |   +---subscripts
|   |   |   +---script_one.py
|   |   |   +---script_two.py

Inside run.py, you can import scripts one and two by:

from subscripts import script_one as One
from subscripts import script_two as Two

Now, still inside run.py, you’ll be able to call their methods with:

One.method_from_one(param)
Two.method_from_two(other_param)

回答 4

只需创建一个空的____init____.py文件,并将其添加到root以及您拥有其他python模块的python应用程序的所有子目录/文件夹中即可。

Just create an empty __init__.py file and add it in root as well as all the sub directory/folder of your python application where you have other python modules. See https://docs.python.org/3/tutorial/modules.html#packages


回答 5

即使子文件夹中存在init .py且在导入后添加“ as” 时仍存在问题

from folder.file import Class as Class
import folder.file as functions

Had problems even when init.py existed in subfolder and all that was missing was adding ‘as’ after import

from folder.file import Class as Class
import folder.file as functions

从Python中的相对路径导入

问题:从Python中的相对路径导入

我有一个用于客户代码的文件夹,一个用于我的服务器代码的文件夹,以及一个在他们之间共享的代码的文件夹

Proj/
    Client/
        Client.py
    Server/
        Server.py
    Common/
        __init__.py
        Common.py

如何从Server.py和Client.py导入Common.py?

I have a folder for my client code, a folder for my server code, and a folder for code that is shared between them

Proj/
    Client/
        Client.py
    Server/
        Server.py
    Common/
        __init__.py
        Common.py

How do I import Common.py from Server.py and Client.py?


回答 0

编辑2014年11月(3年后):

Python 2.6和3.x支持适当的相对导入,在这里您可以避免做任何棘手的事情。使用这种方法,您知道您得到的是相对导入而不是绝对导入。“ ..”表示转到我上方的目录:

from ..Common import Common

请注意,仅当您从包外部将python作为模块运行时,此方法才有效。例如:

python -m Proj

原始的骇客方式

在某些情况下,实际上您从来没有“安装”软件包,这种方法仍然很常用。例如,它在Django用户中很流行。

您可以将Common /添加到您的sys.path中(python用来导入内容的路径列表):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common

os.path.dirname(__file__) 只需为您提供当前python文件所在的目录,然后我们导航至该目录的“ Common /”并导入“ Common”模块。

EDIT Nov 2014 (3 years later):

Python 2.6 and 3.x supports proper relative imports, where you can avoid doing anything hacky. With this method, you know you are getting a relative import rather than an absolute import. The ‘..’ means, go to the directory above me:

from ..Common import Common

As a caveat, this will only work if you run your python as a module, from outside of the package. For example:

python -m Proj

Original hacky way

This method is still commonly used in some situations, where you aren’t actually ever ‘installing’ your package. For example, it’s popular with Django users.

You can add Common/ to your sys.path (the list of paths python looks at to import things):

import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'Common'))
import Common

os.path.dirname(__file__) just gives you the directory that your current python file is in, and then we navigate to ‘Common/’ the directory and import ‘Common’ the module.


回答 1

有趣的是,我刚刚遇到了一个相同的问题,我可以通过以下方式获得这项工作:

结合linux命令ln,我们可以使事情变得更加简单:

1. cd Proj/Client
2. ln -s ../Common ./

3. cd Proj/Server
4. ln -s ../Common ./

而且,现在,如果some_stuff要从file:Proj/Common/Common.py导入到file:中Proj/Client/Client.py,就像这样:

# in Proj/Client/Client.py
from Common.Common import some_stuff

并且,同样适用于Proj/Server,也适用于setup.py过程, 此处讨论的相同问题,希望对您有所帮助!

Funny enough, a same problem I just met, and I get this work in following way:

combining with linux command ln , we can make thing a lot simper:

1. cd Proj/Client
2. ln -s ../Common ./

3. cd Proj/Server
4. ln -s ../Common ./

And, now if you want to import some_stuff from file: Proj/Common/Common.py into your file: Proj/Client/Client.py, just like this:

# in Proj/Client/Client.py
from Common.Common import some_stuff

And, the same applies to Proj/Server, Also works for setup.py process, a same question discussed here, hope it helps !


回答 2

不要做相对导入。

PEP8

强烈建议不要将相对进口用于包装内进口。

将所有代码放入一个超级包(即“ myapp”)中,并将子包用于客户端,服务器和通用代码。

更新:Python 2.6和3.x支持正确的相对导入(…) ”。有关更多详细信息,请参见Dave的答案

Don’t do relative import.

From PEP8:

Relative imports for intra-package imports are highly discouraged.

Put all your code into one super package (i.e. “myapp”) and use subpackages for client, server and common code.

Update:Python 2.6 and 3.x supports proper relative imports (…)“. See Dave’s answers for more details.


回答 3

进行相对导入绝对可以!这是我的小事:

#first change the cwd to the script path
scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
os.chdir(scriptPath)

#append the relative location you want to import from
sys.path.append("../common")

#import your module stored in '../common'
import common.py

Doing a relative import is absolulutely OK! Here’s what little ‘ol me does:

#first change the cwd to the script path
scriptPath = os.path.realpath(os.path.dirname(sys.argv[0]))
os.chdir(scriptPath)

#append the relative location you want to import from
sys.path.append("../common")

#import your module stored in '../common'
import common.py

回答 4

从PYTHONPATH开始,默认的导入方法已经是“相对的”。默认情况下,PYTHONPATH是某些系统库以及原始源文件的文件夹。如果使用-m运行以运行模块,则当前目录将添加到PYTHONPATH中。因此,如果程序的入口点位于Proj内,则import Common.Common在Server.py和Client.py内都可以使用。

不要做相对导入。它不会按您希望的那样工作。

The default import method is already “relative”, from the PYTHONPATH. The PYTHONPATH is by default, to some system libraries along with the folder of the original source file. If you run with -m to run a module, the current directory gets added to the PYTHONPATH. So if the entry point of your program is inside of Proj, then using import Common.Common should work inside both Server.py and Client.py.

Don’t do a relative import. It won’t work how you want it to.


无法在Python中导入我自己的模块

问题:无法在Python中导入我自己的模块

我很难理解模块导入在Python中是如何工作的(我以前从未用任何其他语言来完成过此工作)。

假设我有:

myapp/__init__.py
myapp/myapp/myapp.py
myapp/myapp/SomeObject.py
myapp/tests/TestCase.py

现在,我试图得到这样的东西:

myapp.py
===================
from myapp import SomeObject
# stuff ...

TestCase.py
===================
from myapp import SomeObject
# some tests on SomeObject

但是,我肯定做错了,因为Python看不到这myapp是一个模块:

ImportError: No module named myapp

I’m having a hard time understanding how module importing works in Python (I’ve never done it in any other language before either).

Let’s say I have:

myapp/__init__.py
myapp/myapp/myapp.py
myapp/myapp/SomeObject.py
myapp/tests/TestCase.py

Now I’m trying to get something like this:

myapp.py
===================
from myapp import SomeObject
# stuff ...

TestCase.py
===================
from myapp import SomeObject
# some tests on SomeObject

However, I’m definitely doing something wrong as Python can’t see that myapp is a module:

ImportError: No module named myapp

回答 0

在您的特定情况下,您似乎正在尝试SomeObject从myapp.py和TestCase.py脚本导入。在myapp.py中,执行

import SomeObject

因为它在同一个文件夹中。对于TestCase.py,请执行

from ..myapp import SomeObject

但是,仅当您从软件包中导入TestCase时,此方法才有效。如果要直接运行python TestCase.py,则必须弄乱路径。这可以在Python中完成:

import sys
sys.path.append("..")
from myapp import SomeObject

尽管通常不建议这样做。

通常,如果您希望其他人使用您的Python软件包,则应使用distutils创建安装脚本。这样,任何人都可以使用像这样的命令轻松安装您的软件包,python setup.py install并且该软件包将在其计算机上的所有位置可用。如果您对软件包很认真,甚至可以将其添加到Python软件包索引PyPI中

In your particular case it looks like you’re trying to import SomeObject from the myapp.py and TestCase.py scripts. From myapp.py, do

import SomeObject

since it is in the same folder. For TestCase.py, do

from ..myapp import SomeObject

However, this will work only if you are importing TestCase from the package. If you want to directly run python TestCase.py, you would have to mess with your path. This can be done within Python:

import sys
sys.path.append("..")
from myapp import SomeObject

though that is generally not recommended.

In general, if you want other people to use your Python package, you should use distutils to create a setup script. That way, anyone can install your package easily using a command like python setup.py install and it will be available everywhere on their machine. If you’re serious about the package, you could even add it to the Python Package Index, PyPI.


回答 1

该函数import在PYTHONPATH env中查找文件。变量和您的本地目录。因此,您可以将所有文件放在同一目录中,也可以将键入的路径导出到终端中:

export PYTHONPATH="$PYTHONPATH:/path_to_myapp/myapp/myapp/"

The function import looks for files into your PYTHONPATH env. variable and your local directory. So you can either put all your files in the same directory, or export the path typing into a terminal::

export PYTHONPATH="$PYTHONPATH:/path_to_myapp/myapp/myapp/"

回答 2

导出路径是一个好方法。另一种方法是将.pth添加到您的站点包位置。在我的Mac上,我的python将站点包保存在/ Library / Python中,如下所示

/Library/Python/2.7/site-packages

我在/Library/Python/2.7/site-packages/awesome.pth创建了一个名为awesome.pth的文件,并在文件中放置了以下引用我的超赞模块的路径

/opt/awesome/custom_python_modules

exporting path is a good way. Another way is to add a .pth to your site-packages location. On my mac my python keeps site-packages in /Library/Python shown below

/Library/Python/2.7/site-packages

I created a file called awesome.pth at /Library/Python/2.7/site-packages/awesome.pth and in the file put the following path that references my awesome modules

/opt/awesome/custom_python_modules

回答 3

你可以试试

from myapp.myapp import SomeObject

因为您的项目名称与myapp.py相同,因此它会首先搜索项目文档

You can try

from myapp.myapp import SomeObject

because your project name is the same as the myapp.py which makes it search the project document first


回答 4

在您的第一个myapp目录中,u可以添加setup.py文件,并在setup.py中添加两个python代码

from setuptools import setup
setup(name='myapp')

在命令行的第一个myapp目录中,使用pip install -e。安装软件包

In your first myapp directory ,u can add a setup.py file and add two python code in setup.py

from setuptools import setup
setup(name='myapp')

in your first myapp directory in commandline , use pip install -e . to install the package


回答 5

pip installWindows 10上的默认设置为安装在“ Program Files / PythonXX / Lib / site-packages”中,该目录需要管理权限。因此,我通过以管理员身份运行pip install解决了我的问题 (即使您使用管理员帐户登录,也必须以管理员身份打开命令提示符)。另外,从python调用pip更安全。
例如
python -m pip install <package-name>
代替
pip install <package-name>

pip install on Windows 10 defaults to installing in ‘Program Files/PythonXX/Lib/site-packages’ which is a directory that requires administrative privileges. So I fixed my issue by running pip install as Administrator (you have to open command prompt as administrator even if you are logged in with an admin account). Also, it is safer to call pip from python.
e.g.
python -m pip install <package-name>
instead of
pip install <package-name>


回答 6

就我而言,尽管Windows文件名不区分大小写,但Python导入却使Windows vs Python感到惊讶。因此,如果您有Stuff.py文件,则需要按原样导入此名称。

In my case it was Windows vs Python surprise, despite Windows filenames are not case sensitive, Python import is. So if you have Stuff.py file you need to import this name as-is.


回答 7

你需要

__init__.py

在所有您需要与之交互的代码的文件夹中。即使您尝试导入的文件处于同一级别,也需要在每次导入时指定项目的顶级文件夹名称。

You need to have

__init__.py

in all the folders that have code you need to interact with. You also need to specify the top folder name of your project in every import even if the file you tried to import is at the same level.