使用 py2exe 将 python selenium 脚本构建为 exe
Build a python selenium script into an exe using py2exe
我在 Python3.4 中编写了一个脚本,用于使用 selenium 导航和登录网页。该脚本运行完美。
Selenium 脚本:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://128.114.70.78/periscope")
login = driver.find_element_by_id('keys')
login.send_keys("username")
login.send_keys(Keys.TAB)
login.send_keys("pass")
login.send_keys(Keys.RETURN)
我使用 py2exe 将其构建到 exe 中,但是可执行文件每次都无法导入 selenium webdriver。我收到一个 AttributeError:'NoneType' 对象没有属性 'startswith'。这是日志文件中的错误:
Traceback (most recent call last):
File "periscopeLogin.py", line 1, in <module>
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-packages\selenium\webdriver\__init__.py", line
18, in <module>
from .firefox.webdriver import WebDriver as Firefox # noqa
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-
packages\selenium\webdriver\firefox\webdriver.py", line 34, in <module>
from selenium.webdriver.remote.webdriver import WebDriver as
RemoteWebDriver
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-packages\selenium\webdriver\remote\webdriver.py",
line 25, in <module>
from .webelement import WebElement
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-
packages\selenium\webdriver\remote\webelement.py", line 40, in <module>
getAttribute_js = pkgutil.get_data(__package__,
'getAttribute.js').decode('utf8')
File "C:\Python34\lib\pkgutil.py", line 611, in get_data
spec = importlib.util.find_spec(package)
File "C:\Python34\lib\importlib\util.py", line 81, in find_spec
fullname = resolve_name(name, package) if name.startswith('.') else name
AttributeError: 'NoneType' object has no attribute 'startswith'
我发现了一个 2014 年的帖子,它说要在 setup.py 文件中指定 selenium webdriver 的位置。 Link: Make exe file from python selenium tests
但是,当我尝试线程的解决方案时,我仍然收到相同的错误。
这是我的 setup.py:
from distutils.core import setup
import py2exe
data_files = [('selenium\webdriver\Firefox', ['C:\Python34\Lib\site-
packages\selenium\webdriver\Firefox\webdriver.xpi'])]
# from selenium import webdriver
# from selenium.webdriver.common.keys import Keys
setup(
windows = [{'script': "periscopeLogin.py"}], # the main py file
data_files = data_files,
options = {
'py2exe':
{
'skip_archive': True,
'optimize': 2,
}
}
)
唯一的区别是我使用的是 Python34,而 3 年前的线程使用的是 Python27。我觉得在那段时间里事情可能已经发生了变化。有没有人有任何想法或线索供我遵循?我应该用 27 试一试吗?
谢谢。
我最终使用 python27 来让它工作,并通过将来自多个线程的答案与这个问题放在一起解决了我的问题。
这是我使用的 setup.py 脚本的副本:
from distutils.core import setup
import py2exe
setup(
console=['periscopeLogin.py'], # the main py file
options={
"py2exe":{
"packages": ["os", "linecache"],
"skip_archive": True, # tell script to not create a library folder
"unbuffered": True,
"optimize": 2
}
}
)
我觉得设置
"skip_archive" = True
是个人喜好,但我关注的帖子说要这样做。
最重要的问题是py2exe在创建exe时没有复制一些必要的文件。您可以通过在 python 目录中找到文件并将它们手动复制到 dist 文件夹中来解决此问题。
首先是“getAttribute”和“isDisplayed”。它们可以位于
*pythonDirectory*\Lib\site-packages\selenium\webdriver\remote
我的python目录是C:\python27\,所以我的文件在
C:\Python27\Lib\site-packages\selenium\webdriver\remote.
复制这两个文件,导航到您的 dist 文件夹,然后将它们粘贴到
\dist\selenium\webdriver\remote
如果您使用的是 Internet Explorer webdriver,这就是您需要做的全部。我认为 Chromedriver 也一样,但我没有测试过。
如果您使用的是 Firefox,我知道您还需要复制几个文件。它们是“webdriver.xpi”和“webdriver_prefs.json”。您可以定位
他们在:
*pythonDirectory*\Lib\site-packages\selenium\webdriver\firefox
将它们粘贴到
\dist\selenium\webdriver\firefox
现在你应该可以开始了!
我在 Python3.4 中编写了一个脚本,用于使用 selenium 导航和登录网页。该脚本运行完美。 Selenium 脚本:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Firefox()
driver.get("http://128.114.70.78/periscope")
login = driver.find_element_by_id('keys')
login.send_keys("username")
login.send_keys(Keys.TAB)
login.send_keys("pass")
login.send_keys(Keys.RETURN)
我使用 py2exe 将其构建到 exe 中,但是可执行文件每次都无法导入 selenium webdriver。我收到一个 AttributeError:'NoneType' 对象没有属性 'startswith'。这是日志文件中的错误:
Traceback (most recent call last):
File "periscopeLogin.py", line 1, in <module>
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-packages\selenium\webdriver\__init__.py", line
18, in <module>
from .firefox.webdriver import WebDriver as Firefox # noqa
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-
packages\selenium\webdriver\firefox\webdriver.py", line 34, in <module>
from selenium.webdriver.remote.webdriver import WebDriver as
RemoteWebDriver
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-packages\selenium\webdriver\remote\webdriver.py",
line 25, in <module>
from .webelement import WebElement
File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 1191, in _load_unlocked
File "<frozen importlib._bootstrap>", line 1161, in
_load_backward_compatible
File "C:\Python34\lib\site-
packages\selenium\webdriver\remote\webelement.py", line 40, in <module>
getAttribute_js = pkgutil.get_data(__package__,
'getAttribute.js').decode('utf8')
File "C:\Python34\lib\pkgutil.py", line 611, in get_data
spec = importlib.util.find_spec(package)
File "C:\Python34\lib\importlib\util.py", line 81, in find_spec
fullname = resolve_name(name, package) if name.startswith('.') else name
AttributeError: 'NoneType' object has no attribute 'startswith'
我发现了一个 2014 年的帖子,它说要在 setup.py 文件中指定 selenium webdriver 的位置。 Link: Make exe file from python selenium tests 但是,当我尝试线程的解决方案时,我仍然收到相同的错误。 这是我的 setup.py:
from distutils.core import setup
import py2exe
data_files = [('selenium\webdriver\Firefox', ['C:\Python34\Lib\site-
packages\selenium\webdriver\Firefox\webdriver.xpi'])]
# from selenium import webdriver
# from selenium.webdriver.common.keys import Keys
setup(
windows = [{'script': "periscopeLogin.py"}], # the main py file
data_files = data_files,
options = {
'py2exe':
{
'skip_archive': True,
'optimize': 2,
}
}
)
唯一的区别是我使用的是 Python34,而 3 年前的线程使用的是 Python27。我觉得在那段时间里事情可能已经发生了变化。有没有人有任何想法或线索供我遵循?我应该用 27 试一试吗?
谢谢。
我最终使用 python27 来让它工作,并通过将来自多个线程的答案与这个问题放在一起解决了我的问题。 这是我使用的 setup.py 脚本的副本:
from distutils.core import setup
import py2exe
setup(
console=['periscopeLogin.py'], # the main py file
options={
"py2exe":{
"packages": ["os", "linecache"],
"skip_archive": True, # tell script to not create a library folder
"unbuffered": True,
"optimize": 2
}
}
)
我觉得设置
"skip_archive" = True
是个人喜好,但我关注的帖子说要这样做。
最重要的问题是py2exe在创建exe时没有复制一些必要的文件。您可以通过在 python 目录中找到文件并将它们手动复制到 dist 文件夹中来解决此问题。
首先是“getAttribute”和“isDisplayed”。它们可以位于
*pythonDirectory*\Lib\site-packages\selenium\webdriver\remote
我的python目录是C:\python27\,所以我的文件在
C:\Python27\Lib\site-packages\selenium\webdriver\remote.
复制这两个文件,导航到您的 dist 文件夹,然后将它们粘贴到
\dist\selenium\webdriver\remote
如果您使用的是 Internet Explorer webdriver,这就是您需要做的全部。我认为 Chromedriver 也一样,但我没有测试过。
如果您使用的是 Firefox,我知道您还需要复制几个文件。它们是“webdriver.xpi”和“webdriver_prefs.json”。您可以定位 他们在:
*pythonDirectory*\Lib\site-packages\selenium\webdriver\firefox
将它们粘贴到
\dist\selenium\webdriver\firefox
现在你应该可以开始了!