1

I wrote a script in Python3.4 to navigate and login to a webpage using selenium. The script functions flawlessly. Selenium script:

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)

I built it into an exe using py2exe, however the executable fails to import the selenium webdriver every time. I am getting an AttributeError: 'NoneType' object has no attribute 'startswith'. Here is the error in the log file:

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'

I found a thread from 2014 that says to specify the location of selenium webdriver in the setup.py file. Link: Make exe file from python selenium tests However, I still receive the same error when I try the thread's solution. Here is my 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,
            }
    }
)

The only difference is that I'm using Python34, and the 3 year old thread uses Python27. I feel like things may have changed over that time span. Does anyone have any ideas or leads for me to follow? Should I just give it a shot with 27?

Thank you.

Community
  • 1
  • 1
Kodiak North
  • 71
  • 1
  • 10

1 Answers1

3

I ended up using python27 to get this to work, and solved my problem by putting together the answers from multiple threads with this issue. Here is a copy of the setup.py script I used:

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
            }
    }
)

I think setting

"skip_archive" = True

is a personal preference, but a thread I followed said to do it.

The most significant problem is that py2exe does not copy over a few necessary files when creating the exe. You can fix this by finding the files in your python directory and manually copying them into your dist folder.

The first are "getAttribute" and "isDisplayed". They can be located at

*pythonDirectory*\Lib\site-packages\selenium\webdriver\remote

My python directory is C:\python27\, so my files were found in

C:\Python27\Lib\site-packages\selenium\webdriver\remote.

Copy these two files, navigate to your dist folder, and paste them into

\dist\selenium\webdriver\remote

If you are using the Internet Explorer webdriver, this is all you need to do. I think the same for Chromedriver but I have not tested it.

If you're using Firefox, I know there are a couple more files you need to copy. They are "webdriver.xpi" and "webdriver_prefs.json". You can locate them in:

*pythonDirectory*\Lib\site-packages\selenium\webdriver\firefox

Paste them into

\dist\selenium\webdriver\firefox

Now you should be good to go!

Kodiak North
  • 71
  • 1
  • 10