Pycharm交互式控制台无法工作。

5

我对python和Pycharm都很陌生,因此请不要犹豫指出我的错误并告诉我如何解决问题。

问题是IPython无法像通常一样导入我想要执行的函数。即使python文件运行后,我仍然不能在IPython控制台中从该文件导入函数。另外,在IPython控制台中也没有代码补全功能。

例如,我编写了一个名为student.py的python文件,在其中定义了一个名为student的类。然后我运行了这个文件。但是当我在控制台中输入student('Jack', 28)时,IPython控制台会提示类'student'未定义。

class student(object):
    def _init_(self, name, age):
        self.name=name
        self.age=age

我感到困惑的是,我可以运行这个文件。但是当我在控制台中输入student('Jack', 28)时,IPython控制台会提示:
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/IPython/core/interactiveshell.py", line 3032, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-2-483e7a488507>", line 1, in <module>
student('Jack',28)
NameError: name 'student' is not defined

此外,在IPython控制台中,IPython魔术函数也无法正常工作。
In[3]: %run student.py
ERROR: File `u'student.py'` not found.

很抱歉由于声誉不够,无法提供图片以更清晰地说明情况。


你能否发布你在控制台中输入的完整命令列表? - Chintalagiri Shashank
当然,我已经更新了问题描述。 - Jason
你尝试过“run -m student”吗? - Chintalagiri Shashank
我试过了,但还是不行。我输入了 run -m student,结果显示 u'student' 不是 sys.path 上的有效模块名称。 - Jason
2个回答

3

如果想要在执行后保留对象/类/函数/变量,您需要更改运行>编辑配置>解释器选项中的解释器选项,然后添加-i。我仍然不清楚控制台中的代码完成。


谢谢,我打开了“运行>编辑配置>解释器选项”,但我不知道在哪里添加“-i”。您能否更明确地解释一下? - Jason
我找到了“解释器选项”,并输入了“-i student.py”。但是它没有起作用。 - Jason
只需键入 -i 然后应用它并像往常一样运行您的代码。 - Shivendra
谢谢,这正是我所需要的。有一个问题,"-i"选项实际上是做什么的?它会影响解释器的性能吗? - Cina
它代表交互模式。这是Python命令行的一个特性,而不是PyCharm的,因此它可以在任何控制台/终端上使用。 - Shivendra
不会影响性能。我建议您在PyCharm中使用IPython控制台而不是带有-i选项的Python - Shivendra

2
这取决于你如何“运行”python文件。从pycharm内部有很多种方法可以做到这一点(可能太多了)。
我猜你正在按下绿色三角形。这不会在存在于底部的“Python Console”选项卡中的同一shell中执行文件。它代替生成一个新的shell,执行文件,并默认情况下在文件执行完成时关闭shell。您可以在“Run”选项卡中看到此Shell的操作过程。从Shivendra的回复中可以看出,似乎有一种方法可以避免在脚本退出时终止shell。如果确实是这样,那么您将使用保留在“Run”选项卡中而非在“Python控制台”选项卡中的终端/ shell。
这与使用Debug而非Run时发生的情况非常相似。它生成一个解释器,附加调试器,运行脚本,在所有操作完成后杀死进程。这保存在“Debug”选项卡中。
实现您想要的最简单的方法是在预先存在的“Python Console”中运行文件,如下所示。在这种情况下,脚本会像__main__一样运行,因此,如果您有一个if __name__ == "__main__",它将计算为True,并且if块中的任何代码也将被执行。(稍后再详细介绍,如果您现在不知道它是什么)
In[2]: dir()
Out[2]: 
['In',
 'Out',
 '_',
 '__',
 '___',
 '__builtin__',
 '__builtins__',
 '__doc__',
 '__name__',
 '__package__',
 '_dh',
 '_i',
 '_i1',
 '_i2',
 '_ih',
 '_ii',
 '_iii',
 '_oh',
 '_sh',
 'exit',
 'get_ipython',
 'quit',
 'sys']
In[3]: run -m conventions.iec60063
In[4]: dir()
Out[4]: 
['Decimal',
 'E12',
 'E24',
 'E3',
 'E6',
 'In',
 'Out',
 '_',
 '_3',
 '__',
 '___',
 '__builtin__',
 '__builtins__',
 '__doc__',
 '__loader__',
 '__name__',
 '__nonzero__',
 '__package__',
 '_dh',
 '_i',
 '_i1',
 '_i2',
 '_i3',
 '_i4',
 '_ih',
 '_ii',
 '_iii',
 '_oh',
 '_sh',
 'cap_ostrs',
 'elem',
 'exit',
 'gen_vals',
 'get_ipython',
 'get_series',
 'idx',
 'ind_ostrs',
 'quit',
 'res_ostrs',
 'sys',
 'zen_ostrs']

我偏好的“运行”文件的方式是从“Python Shell”(IPython或其他)中导入它,并手动运行需要运行的任何初始化代码。这样做的优点是不会过度污染名称空间,并呈现一个更接近于使用脚本作为模块时所期望的环境(这里是PyCharm和IPython以及自动补全真正开始发挥作用的地方)。在两种方法中,您都可以选择使用“附加调试器”图标将调试器连接到“Python Console”的解释器上(绿色bug旁边)。

以下是一个简短的示例(在“Python Console”选项卡中):

In[2]: dir()
Out[2]: 
['In',
 'Out',
 '_',
 '__',
 '___',
 '__builtin__',
 '__builtins__',
 '__doc__',
 '__name__',
 '__package__',
 '_dh',
 '_i',
 '_i1',
 '_i2',
 '_ih',
 '_ii',
 '_iii',
 '_oh',
 '_sh',
 'exit',
 'get_ipython',
 'quit',
 'sys']
In[3]: import conventions.iec60063
In[4]: dir()
Out[4]: 
['In',
 'Out',
 ... (all the same ones as before)
 'conventions',
 ... (all the same ones as before)
]

实际上,您并不会直接运行文件,因此应该了解您正在做什么。
当您执行Python文件时,模块认为它的__name__"__main__",这就是if __name__ == "__main__"技巧的起源(这是您在Python学习过程中应该早期了解的内容)。如果您尝试跟踪代码的执行,解释器会执行模块中不是类或函数的所有内容。这包括您将在许多Python脚本中看到的if __name__ == "__main__"条件。 if块的内容只有在脚本独立运行(或使用run -m module在IPython中运行)时才会被执行。
另一方面,当您导入一个模块时,相同的执行顺序发生了变化,除了if __name__ == "__main__"将计算为False,任何位于该块中的代码都不会被调用。因此,如果需要,则应手动执行if __name__ == "__main__"块中的任何内容。简化该任务的一种常见模式是只在if块内具有最小的函数调用(或者,如果您关心命令行参数,请在那里处理这些参数),然后将大部分执行转交给易于调用的函数。
def main():
    pass

if __name__ == "__main__":
    main()

如果您导入模块后需要执行其中的代码,则只需调用 main() 函数即可。在上面的示例中,如果我必须在模块“运行”时执行一些代码,我会这样做:

In[2]: import conventions.iec60063
In[3]: conventions.iec60063.main()

Pycharm有一些更加高级的执行代码的方式(例如仅执行文件的一小部分等),但我并没有真正需要它们,所以不太清楚它们的工作原理。


问题在于类型run -m studentimport student都无法正常工作。IPython显示对于run -m方法,u'student' is not a valid modulename on sys.path,而对于import方法则显示No module named student - Jason
在设置中检查 > 构建、执行、部署 > 控制台 > Python控制台。您应该在起始脚本中有类似 sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS] 的内容。我使用默认值(我期望 - 不记得更改它)选择将内容根目录添加到PYTHONPATH,并且为了能够导入student或运行-m student或其他内容,student.py应该存在于您的根文件夹中或称为student的包(带有__init__.py的文件夹)应该存在于项目根目录中。 - Chintalagiri Shashank
如果学生在子文件夹中,您将不得不使用相对于项目根目录的路径导入它。 如果您的文件结构是<projectname>/somedirectory/student.py,则应该使用import somedirectory.student as studentrun -m somedirectory.student。 我期望somedirectory也必须是一个包,即必须有一个__init__py文件(空文件即可)。 - Chintalagiri Shashank
感谢您的建议。我已经解决了run -m的问题。这可能是由于在student.py路径中有一个以中文命名的文件夹。然而,在成功运行run -m student.py之后,当我输入student('Amy', 12)时,IPython控制台显示“object() takes no parameters”。但是我可以在ipython qt-console中运行该文件。 - Jason
检查一下你的代码和命名空间,很可能在某个地方使用了不一致的命名空间。 - Chintalagiri Shashank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接