我已经在centos上安装了Firefox和Selenium。我正在使用Xvfb和pyvirtualdisplay来打开浏览器。
当我尝试运行selenium webdriver时,我能够尽快打开新的显示器
browser = webdriver.Firefox()
我收到错误:
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/site-packages/selenium/webdriver/firefox/webdriver.py", line 134, in __init__
self.service = Service(executable_path, log_path=log_path)
File "/usr/lib/python2.7/site-packages/selenium/webdriver/firefox/service.py", line 45, in __init__
log_file = open(log_path, "a+")
IOError: [Errno 13] Permission denied: 'geckodriver.log'
关于这里出了什么问题的任何线索?
编辑:克服了权限错误后,我正在
Message: 'geckodriver' executable needs to be in PATH
答案 0 :(得分:4)
我遇到了同样的问题。我尝试使用Ivan Chaer的答案,但它没有用。我尝试了很多其他的东西,直到我终于遇到了一个有效的解决方案。我一直在尝试运行Selenium,我一直在使用交互式shell。当我尝试将代码放在脚本中然后运行它时,一切正常。
然后我注意到,在与脚本相同的目录中创建了一个名为“geckodriver.log”的文件。这给了我一个主意。我在C:\ Program Files \ Python36中创建了一个“geckodriver.log”文件,然后使用Selenium和Firefox不再犯任何错误。
答案 1 :(得分:3)
显然,这可能来自你的firefox和你的Selenium之间的不兼容。试试pip install --upgrade selenium
,如果错误仍然存在,请尝试downloading a different version of Firefox或gecko driver。
关于消息:
'geckodriver' executable needs to be in PATH
您可以在脚本上设置驱动程序的路径:
ff_profile_dir = "/usr/local/selenium/webdriver/firefox"
ff_profile = selenium.webdriver.FirefoxProfile(profile_directory=ff_profile_dir)
driver = selenium.webdriver.Firefox(ff_profile)
或者,根据this answer,您可以在Unix系统上运行与bash兼容的shell:
export PATH=$PATH:/path/to/directory/of/executable/downloaded/in/previous/step
在Windows上,您需要更新Path系统变量才能添加 手动或命令的可执行geckodriver的完整目录路径 line(添加可执行文件后别忘了重启系统 geckodriver进入系统PATH生效)。原则是 和Unix一样。
答案 2 :(得分:1)
以下解决方案适合我。就我而言,我是从Windows Notepad++
应用程序中启动我的Python脚本。我的geckodriver.exe
位于PATH中,恰好位于我的C:\Python 27
文件夹中。还提供了完整的Firefox路径。 Selenium,geckodriver和Firefox都是最新版本。
事实证明,geckodriver.log
文件是在这里创建的:
C:\Program Files (x86)\Notepad++\geckodriver.log
我是以管理员身份运行Notepad++
找到的。然后它可以创建它想要的文件。然后我找到了该文件并将文件权限更改为Windows上普通用户帐户的完全访问权限(它被设置为只读)。
执行此操作后,我能够正常运行Notepad ++并且错误消失了。
答案 3 :(得分:1)
在使用python IDLE时,我遇到了同样的问题。
我只是以管理员的身份运行IDLE shell。
现在运行以下命令可以正常工作。
from selenium import webdriver
browser = webdriver.Firefox() #opens up a new Firefox window
答案 4 :(得分:0)
我有完全相同的问题。我继续进行selenium's pypi page。在“驱动程序”部分,他们谈论了geckodriver,您可以找到适合您的浏览器和操作系统的geckodriver可执行文件的链接。
我刚刚下载了该文件,将其解压缩,然后将geckodriver.exe文件放置在C:\ Program Files \ Python37中(Python37已经在我的PATH中)。现在可以正常使用了。
答案 5 :(得分:0)
在我的案例中,geckodriver.log是在脚本文件夹上创建的,但是由root用户通过先前的执行,它们以普通用户python的身份再次运行,但是他们无法访问文件并失败
答案 6 :(得分:0)
我最近在Windows 10工作站上遇到了同样的问题。我通过将service_log_path显式设置为我知道可以写到的位置来修复它:
class TreeButtonDelegate(QtWidgets.QStyledItemDelegate):
buttonClicked = QtCore.pyqtSignal(QtCore.QModelIndex, int)
def __init__(self, fsModel, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fsModel = fsModel
self.clickedPaths = {}
self._mousePos = None
self._pressed = False
self.minimumButtonWidth = 32
def getOption(self, option, index):
btnOption = QtWidgets.QStyleOptionButton()
# initialize the basic options with the view
btnOption.initFrom(option.widget)
clickedCount = self.clickedPaths.get(self.fsModel.filePath(index), 0)
if clickedCount:
btnOption.text = '{}'.format(clickedCount)
else:
btnOption.text = 'NO'
# the original option properties should never be touched, so we can't
# directly use it's "rect"; let's create a new one from it
btnOption.rect = QtCore.QRect(option.rect)
# adjust it to the minimum size
btnOption.rect.setLeft(option.rect.right() - self.minimumButtonWidth)
style = option.widget.style()
# get the available space for the contents of the button
textRect = style.subElementRect(
QtWidgets.QStyle.SE_PushButtonContents, btnOption)
# get the margins between the contents and the border, multiplied by 2
# since they're used for both the left and right side
margin = style.pixelMetric(
QtWidgets.QStyle.PM_ButtonMargin, btnOption) * 2
# the width of the current button text
textWidth = btnOption.fontMetrics.width(btnOption.text)
if textRect.width() < textWidth + margin:
# if the width is too small, adjust the *whole* button rect size
# to fit the contents
btnOption.rect.setLeft(btnOption.rect.left() - (
textWidth - textRect.width() + margin))
return btnOption
def editorEvent(self, event, model, option, index):
# map the proxy index to the fsModel
srcIndex = index.model().mapToSource(index)
# I'm just checking if it's a file, if you want to check the extension
# you might need to use fsModel.fileName(srcIndex)
if not self.fsModel.isDir(srcIndex):
if event.type() in (QtCore.QEvent.Enter, QtCore.QEvent.MouseMove):
self._mousePos = event.pos()
# request an update of the current index
option.widget.update(index)
elif event.type() == QtCore.QEvent.Leave:
self._mousePos = None
elif (event.type() in (QtCore.QEvent.MouseButtonPress, QtCore.QEvent.MouseButtonDblClick)
and event.button() == QtCore.Qt.LeftButton):
# check that the click is within the virtual button rectangle
if event.pos() in self.getOption(option, srcIndex).rect:
self._pressed = True
option.widget.update(index)
if event.type() == QtCore.QEvent.MouseButtonDblClick:
# do not send double click events
return True
elif event.type() == QtCore.QEvent.MouseButtonRelease:
if self._pressed and event.button() == QtCore.Qt.LeftButton:
# emit the click only if the release is within the button rect
if event.pos() in self.getOption(option, srcIndex).rect:
filePath = self.fsModel.filePath(srcIndex)
count = self.clickedPaths.setdefault(filePath, 0)
self.buttonClicked.emit(index, count + 1)
self.clickedPaths[filePath] += 1
self._pressed = False
option.widget.update(index)
return super().editorEvent(event, model, option, index)
def paint(self, painter, option, index):
super().paint(painter, option, index)
srcIndex = index.model().mapToSource(index)
if not self.fsModel.isDir(srcIndex):
btnOption = self.getOption(option, srcIndex)
# remove the focus rectangle, as it will be inherited from the view
btnOption.state &= ~QtWidgets.QStyle.State_HasFocus
if self._mousePos is not None and self._mousePos in btnOption.rect:
# if the style supports it, some kind of "glowing" border
# will be shown on the button
btnOption.state |= QtWidgets.QStyle.State_MouseOver
if self._pressed == QtCore.Qt.LeftButton:
# set the button pressed state
btnOption.state |= QtWidgets.QStyle.State_On
else:
# ensure that there's no mouse over state (see above)
btnOption.state &= ~QtWidgets.QStyle.State_MouseOver
# finally, draw the virtual button
option.widget.style().drawControl(
QtWidgets.QStyle.CE_PushButton, btnOption, painter)
class MainMenu(QWidget):
def __init__(self, parent = None):
super(MainMenu, self).__init__(parent)
# ...
self.treeView = QTreeView(self)
self.treeView.setMouseTracking(True)
# ...
self.treeDelegate = TreeDelegate(self.model)
self.treeView.setItemDelegateForColumn(0, self.treeDelegate)
self.treeDelegate.buttonClicked.connect(self.treeButtonClicked)
# ...
def treeButtonClicked(self, index, count):
print('{} clicked {} times'.format(index.data(), count))
答案 7 :(得分:0)
我有这个完全相同的错误。
[Errno 13] Permission denied: 'geckodriver.log'
此.log文件根本没有问题。
真正的问题是我的脚本(.py文件)和geckodriver.exe不在同一文件夹中。
将它们放在同一文件夹中后,问题就解决了,功能正常执行了。
browser = webdriver.Firefox()
希望这会有所帮助。
答案 8 :(得分:0)
我在尝试在我的 webdriver(我使用的是 Firefox 的 geckodriver)所在的位置运行交互式 shell 时遇到了同样的问题,但什么也没发生,我得出的结论是该目录没有写入权限当你成功时,因此我使用 chmod(在 Linux 上)设置了写入权限,一切都按预期工作。请务必先检查权限,看看您是否可以首先创建 geckodriver.log 文件。
答案 9 :(得分:-1)
我尝试在 python IDLE 上执行此代码时遇到了同样的问题,但是当我切换到 VScode 时,它开始工作得很好。