How to run pycharm unittests when standard lib is zipped? - python

I've been trying to port a Maya based python project over to PyCharm but I'm having trouble running unit tests.
Maya provides its own python interpreter (mayapy.exe) with a zipped version of the python stdlib (in this case, 'Python27.zip') AFAIK there's nothing special about the stdlib here, but to run the native maya functions you have to use MayaPy rather than a generic python.
The problem appears to be that the jetBrains test runner (utRunner.py) wants to get os.system and it's barfing because it uses a specific import routine that doesn't allow for zip files. It tries this:
def import_system_module(name):
if sys.platform == "cli": # hack for the ironpython
return __import__(name)
f, filename, desc = imp.find_module(name)
return imp.load_module('pycharm_' + name, f, filename, desc)
and fails with this error:
ImportError: No module named os
I think because this is bypassing the zip import hook.
There's one solution posted here, which is basically to unzip the standard library zip. I'm reluctant to do that because I might need to run the tests on machines where I don't have admin rights. I'm also reluctant to patch the code above since I'm not clear how it fits in to the whole test process.
So: how to run tests with a zipped standardlib using PyCharm, without unzipping the library or tweaking the PyCharm install too much?

For lurkers: I was unable to find a better solution than the one linked above, so it was necessary to unzip the 2.7 standard libary into a loose folder. Inelegant, but it works,.
There was a further wrinkle that maya users need to watch out for: PyCharm does not like tests which run Maya.standalone -- the standalone session did not exit properly, so when running tests (in onr ore more files) that called
import maya.standalone
maya.standalone.initialize()
The pycharm test runner would hang on completion. After much frustration I found that adding an atexit handler to the test code would allow the standalone to exit in a way that PyCharm could tolerate:
def get_out_of_maya():
try:
import maya.commands as cmds
cmds.file(new=True, force=True)
except:
pass
os._exit(0) # note underscore
import atexit
atexit.register(get_out_of_maya)
This pre-empts the atexit hook in Maya and allows the tests to complete to the satisfaction of the Pycharm runner. FWIW, it also helps if you are running MayaPy.exe from a subprocess and executing your tests that way.

I ended up just editing Pycharm's utrunner.py file. It already imports os at the top of the file, so I'm not sure why it calls import_system_module. The import command automatically handles zip files. Also if you put the maya.standalone in the runner file, you don't need to call it in any of your test files.
#os = import_system_module("os")
#re = import_system_module("re")
import re
try:
import maya.standalone
maya.standalone.initialize()
except ImportError:
pass
I'm using Pycharm 5.0.1.

Related

pyinstaller: popen doesn't run after producing exe

I compiled my python application using pyinstaller and the exe works fine, but when I run it on a different machine without python any part of the code which contains subprocess.Popen()doesn't run.
I read too many questions but I couldn't wrap my head around this.
My popen line:
try:
process = subprocess.Popen(['python', os.path.abspath('about.py')],stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,
shell=True)
except Exception as e:
print(e)
Note that the executable runs on the host machine, but on another machines it runs but fails when launching the popen.
===UPDATE====
The console shows nothing and doesn't print an exception, so I guess this is a problem with python not being found. How can I fix this?
===UPDATE2====
Following the suggestion of viilpe I used "exec(open..." but it required me to import the about.py module first; importing the module runs it on top of the main module.
Putting exec(open...) inside the try\except runs the main module and the about module alongside each other; ruining the application's GUI.
I'm using "kivy" as my GUI library.
Looks like you want to execute about.py but there is no python.exe in pyinstaller bundle.
As advised here you can do it this way:
exec(open('about.py').read())
The whole point of PyInstaller is to make the destination computer be able to run your script without having a standalone python installation. You can't run a subprocess on a tool which isn't (necessarily) installed.
There are various ways to run Python as a subprocess of itself natively; start by exploring the multiprocessing library.
If the requirement to run Python twice is not a hard one, the absolutely simplest solution is to import about and run the code as part of your script. This probably requires some refactoring of the code in about.py.

Running behave within Eclipse/PyDev

I'd like to be able to run behave from the context menu within the PyDev project explorer (i.e. right click (on a feature file or directory) Run As- Behave and have it run the feature file (or files) once run the any errors in the output would take you to the line in the file it refers to.
Is this possible?
I have set behave up as an external tool, which works but it isn't great
PyDev doesn't support behave directly but it does support pytest, so, my suggestion is using behave through pytest (you have to configure the test runner to be pytest -- see: https://www.pydev.org/manual_adv_pyunit.html).
It seems that the related pytest plugin for running behave is: https://pypi.org/project/pytest-bdd/
Eclipse (and PyDev) supports running other "External Tools" / Commands.
For behave, you just need to provide the definition to run a python script.
If anything fails, provide your own "run_behave.py" scripts that runs behave (much like the "behave script"). This also simplifies debugging.
It's possible, but as #jenisys noted, you have to make a tiny behave-runner like this (copied from the bin/behave command):
#!/path/to/your/env/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from behave.__main__ import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())
Run this, then modify the run / debug configuration with the behave command line arguments, and you're up and running (or debugging)!

How can I import a Python script with several modules included into Sikuli

I'm trying to call a Python (2.7) script from Sikuli (r930) and use a variable from the script. Below is the Python code:
import sys
import re
import os
import time
from pywinauto import application
from SendKeys import SendKeys
from cStringIO import StringIO
app=application.Application()
app.connect_(path=r'C:\Program Files\myApp\myApp.exe')
backup = sys.stdout
sys.stdout = StringIO()
app.dlg.print_control_identifiers()
out = sys.stdout.getvalue()
sys.stdout.close() # close the stream
sys.stdout = backup # restore original stdout
regex = re.compile(r'(\d{8}\s*\-\s*\d{8})')
found = re.search(regex, out)
print found.group(0) #pass this variable to Sikuli
I'm capturing stdout because this is what Pywinauto's print_control_identifiers method returns (not a string). Also, I need a hashed serial number from the GUI app that I can't get with Sikuli, hence the need to use Pywinauto. However, when I attempt to call execfile() from Sikuli, I get the error:
ImportError: no module named Pywinauto.
I read the docs, and I know that Sikuli (Jython) can include Python modules and scripts. Besides, the external .py file that I'm calling runs successfully when ran independently. Can someone tell me if I'm missing a step?
Code I'm using to call the .py file shown above from Sikuli:
aScript = 'c:\\getHash_serial.py'
execfile(aScript)
The immediate problem you're having is that Jython can't find your module. Probably, you installed it under Python, and they don't share a module path. You can fix this by setting the JYTHONPATH environment variable.
However, Pywinauto links with native code, and this is something that Jython does not support.
You may be able to get around this limitation by calling regular Python from Jython via the subprocess module.

How to run a Python script from another Python script in the cross-platform way?

Here is the problem...
I'm writing very small plugin for Blender,
I have 10 python scripts, they parsing different file formats by using command-line, and I have a Main Python script to run all other scripts with proper commands...
for example, "Main.py" include:
txt2cfg.py -inFile -outFile...
ma2lxo.py -inFile -outFile...
Blender already include Python, so I can run "Main.py" from Blender, But I need it to work with both PC and MAC, and also doesn't require Python installation, so I can't use:
execfile(' txt2cfg.py -inFile -outFile ')
os.system(' ma2lxo.py -inFile -outFile ')
or even import subprocess
because they required Python installation in order to run *.py files.
Sorry for language
Thanks
If you really need to execute a python script in a new process and you don't know where the interpreter you want is located then use the sys module to help out.
import sys
import subprocess
subprocess.Popen((sys.executable, "script.py"))
Though importing the module (dynamically if need be) and then running its main method in another script is probably a better idea.
for example, "Main.py" include:
txt2cfg.py -inFile -outFile...
ma2lxo.py -inFile -outFile...
Two things.
Each other script needs a main() function and a "main-import switch". See http://docs.python.org/tutorial/modules.html#executing-modules-as-scripts for hints on how this must look.
Import and execute the other scripts.
import txt2cfg
import ma2lxo
txt2cfg.main( inFile, outFile )
ma2lxo.main( inFile, outFile )
This is the simplest way to do things.
Two options:
Use py2exe to bundle the interpreter with the scripts.
Import the modules and call the functions automatically.

import problem with twisted.web server

I'm just getting started with twisted.web, and I'm having trouble importing a Python module into a .rpy script.
in C:\py\twisted\mysite.py, I have this:
from twisted.web.resource import Resource
from twisted.web import server
class MySite(Resource):
def render_GET(self, request):
request.write("<!DOCTYPE html>")
request.write("<html><head>")
request.write("<title>Twisted Driven Site</title>")
request.write("</head><body>")
request.write("<h1>Twisted Driven Website</h1>")
request.write("<p>Prepath: <pre>{0}</pre></p>".format(request.prepath))
request.write("</body></html>")
request.finish()
return server.NOT_DONE_YET
and in C:\py\twisted\index.rpy, I have this:
import mysite
reload(mysite)
resource = mysite.MySite()
I ran twistd -n web --port 8888 --path C:\py\twisted in command prompt and the server started successfully. But when I requested localhost:8888 I got a (huge) stack trace originating from an ImportError:
<type 'exceptions.ImportError'>: No module named mysite
I can import the module from the interpreter, and if i just execute index.rpy as a python script, I don't get the import error. The documentation on this subject is a bit vague, it just says "However, it is often a better idea to define Resource subclasses in Python modules. In order for changes in modules to be visible, you must either restart the Python process, or reload the module:" (from here).
Does anyone know the proper way to do this?
Short answer: you need to set PYTHONPATH to include C:\py\twisted.
Long answer...
An rpy script is basically just some Python code, like any other Python code. So an import in a rpy script works just like an import in any other Python code. For the most common case, this means that the directories in sys.path are visited one by one, in order, and if a .py file matching the imported name is found, that file is used to define the module.
sys.path is mostly populated from a static definition including things like C:\Python26\Lib\ and from the PYTHONPATH environment variable. However, there's one extra thing worth knowing about. When you run "python", the current working directory is added to the front of sys.path. When you run "python C:\foo\bar\baz.py", C:\foo\bar\' is added to the front ofsys.path. But when you run "twistd ...", nothing useful is added tosys.path`.
This last behavior probably explains why your tests work if you run the rpy script directly, or if you run python and try to import the module interactively, but fail when you use twistd. Adding C:\py\twisted to the PYTHONPATH environment variable should make the module importable when the rpy script is run from the server you start with twistd.

Categories

Resources