可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I initiated and close phantomjs
in Python with the following
from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get(url)
html_doc = driver.page_source
driver.close()
yet after the script ends execution I still find an instance of phantomjs
in my Mac Activity Monitor. And actually every time I run the script a new process phantomjs
is created.
How should I close the driver?
回答1:
The .close()
method is not guaranteed to release all resources associated with a driver instance. Note that these resources include, but may not be limited to, the driver executable (PhantomJS, in this case). The .quit()
method is designed to free all resources of a driver, including exiting the executable process.
回答2:
As of July 2016, driver.close()
and driver.quit()
weren't sufficient for me. That killed the node
process but not the phantomjs
child process it spawned.
Following the discussion on this GitHub issue, the single solution that worked for me was to run:
import signal
driver.service.process.send_signal(signal.SIGTERM) # kill the specific phantomjs child proc
driver.quit() # quit the node proc
回答3:
Please note that this will obviously cause trouble if you have several threads/processes starting PhantomJS on your machine.
I've seen several people struggle with the same issue, but for me, the simplest workaround/hack was to execute the following from the command line through Python AFTER you have invoked driver.close()
or driver.quit()
:
pgrep phantomjs | xargs kill
回答4:
I was having a similar issue on Windows machine. I had no luck with either
driver.close()
or
driver.quit()
actually closing out of the PhantomJS window, but when I used both, the PhantomJS window finally closed and exited properly.
driver.close()
driver.quit()
回答5:
driver.quit()
did not work for me on Windows 10, so I ended up adding the following line right after calling driver.close()
:
os.system('taskkill /f /im phantomjs.exe')
where
/f = force
/im = by image name
And since this is a Windows only solution, it may be wise to only execute if os.name == 'nt'
回答6:
What is the OS you are using? I think it corresponds to the case of the next, if you are using the POSIX OS.
I create pull request, but it rejected.
https://github.com/SeleniumHQ/selenium/pull/2244
But I think obviously the correct it. Therefore , I issued a issue.
https://github.com/SeleniumHQ/selenium/issues/2272
The root cause of this problem is that the end method of ghost driver mode phatmojs is incorrect. It is not not use the shutdown API of ghost driver mode phantomjs at the end.
In the case of phantomjs that you installed in npm on Linux or OSX,
A selenium call Popen for phantomjs, A phantomjs call spawn for lib/phantomjs.js. At this time, a selenium is parent, a phantomjs is child, and lib/phantomjs.js is grandchild.
You call quit() in parent(selenium), it send SIGTERM to child(phantomjs). and a child(phantomjs) send SIGTERM to grandchild(lib/phantomjs.js) in the child's SIGTERM handler function.
A grandchild will be zombie when parent send SIGKILL to child before the child send SIGTERM to grandchild.
This pull request ttps://github.com/SeleniumHQ/selenium/pull/2244 be shutdown using ghost driver mode shutdown api.
def send_remote_shutdown_command(self):
super(Service, self).send_remote_shutdown_command() ## ADD A NEW LINE HERE
if self._cookie_temp_file:
os.close(self._cookie_temp_file_handle)
os.remove(self._cookie_temp_file)
Other solutions, sleep between "self.process.ternimate()" and "self.process.kill()".
ttps://github.com/SeleniumHQ/selenium/blob/051c8b110a1aec35247cd45fa4db85c6e522cdcb/py/selenium/webdriver/common/service.py#L151-L153
self.process.terminate()
time.sleep(1) ## ADD A NEW LINE HERE
self.process.kill()
self.process.wait()
回答7:
I also have a python script running on my mac using selenium to do some stuff using PhantomJS as the webdriver.
When my test is running, there are three processes to note are here:
$ ps -ef | grep [p]hantomjs
501 28085 24925 0 9:03pm ttys002 0:00.34 python test.py
501 28088 28085 0 9:03pm ttys002 0:00.14 node /usr/local/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
501 28090 28088 0 9:03pm ttys002 0:00.71 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
Note the second column which are the process numbers, and the third which are that processes parent.
My test script is the parent. There is a node process which has my test script as a parent, then there is another PhantomJS process whose parent is the node process. Don't ask me why there's two PhantomJS processes, I guess it is just how it's designed to work?
Anyway, in my mac's activity monitor, I can see this:
Note the PID number 28090.
After my test finishes running this, processes hangs around, just like you too. If I check for still running processes I can see:
$ ps -ef | grep [p]hantomjs
501 28090 1 0 9:03pm ttys002 0:18.93 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs --cookies-file=/var/folders/nq/hjz03w6d4fs620197d_zwg0m0000gn/T/tmp8xLNaH --webdriver=55075
So it appears to me that driver.quit()
exits the node process, the one with PID number 28088, but it leaves its child orphaned. I don't know if this is intentional. If it's not intentional, then I think there isn't a 'proper' way to exit this process in your code.
Therefore I would use your language's equivalent of kill -9 28090
, just after driver.quit()